Documentation
¶
Overview ¶
Package customerror provides the base block to create custom errors. It also provides built-in custom errors covering some common cases. A Custom Error provides context - a `Message` to an optionally wrapped `Err`. Additionally a `Code` - for example "E1010", and `StatusCode` can be provided. Both static (pre-created), and dynamic (in-line) errors can be easily created. `Code` helps a company build a catalog of errors, which helps, and improves customer service.
Examples:
See `example_test.go` or the Example section of the GoDoc documention.
Index ¶
- Variables
- func AddNewLanguage(language string, errorTypePrefixTemplateMap ErrorPrefixMap) error
- func From(err error, opts ...Option) error
- func GetTemplate(language, errorType string) (string, error)
- func IsCustomError(err error) bool
- func IsErrorCode(err error, code string) bool
- func IsHTTPStatus(err error, statusCode int) bool
- func IsRetryable(err error) bool
- func MustAddNewLanguage(language string, errorTypePrefixTemplateMap ErrorPrefixMap)
- func New(message string, opts ...Option) error
- func NewFailedToError(message string, opts ...Option) error
- func NewHTTPError(statusCode int, opts ...Option) error
- func NewInvalidError(message string, opts ...Option) error
- func NewMissingError(message string, opts ...Option) error
- func NewNotFoundError(message string, opts ...Option) error
- func NewRequiredError(message string, opts ...Option) error
- func Wrap(customError error, errors ...error) error
- type Catalog
- func (c *Catalog) Get(errorCode string, _ ...Option) (*CustomError, error)
- func (c *Catalog) MustGet(errorCode string, opts ...Option) *CustomError
- func (c *Catalog) MustSet(errorCode string, defaultMessage string, opts ...Option) *Catalog
- func (c *Catalog) Set(errorCode string, defaultMessage string, opts ...Option) (string, error)
- type CustomError
- func (cE *CustomError) APIError() string
- func (cE *CustomError) Error() string
- func (cE *CustomError) FormatError(errorType string, opts ...Option) *CustomError
- func (cE *CustomError) Is(err error) bool
- func (cE *CustomError) JustError() string
- func (cE *CustomError) MarshalJSON() ([]byte, error)
- func (cE *CustomError) New(opts ...Option) error
- func (cE *CustomError) NewChildError(opts ...Option) *CustomError
- func (cE *CustomError) NewFailedToError(opts ...Option) error
- func (cE *CustomError) NewHTTPError(statusCode int, opts ...Option) error
- func (cE *CustomError) NewInvalidError(opts ...Option) error
- func (cE *CustomError) NewMissingError(opts ...Option) error
- func (cE *CustomError) NewRequiredError(opts ...Option) error
- func (cE *CustomError) SetMessage(message string)
- func (cE *CustomError) SetRetried(status bool)
- func (cE *CustomError) Unwrap() error
- type ErrorCode
- type ErrorCodeErrorMap
- type ErrorPrefixMap
- type ErrorType
- type Language
- type LanguageErrorMap
- type LanguageMessageMap
- type Option
- func WithError(err error) Option
- func WithErrorCode(code string) Option
- func WithField(key string, value any) Option
- func WithFields(fields map[string]interface{}) Option
- func WithIgnoreFunc(f func(cE *CustomError) bool) Option
- func WithIgnoreString(s ...string) Option
- func WithLanguage(lang string) Option
- func WithMessage(msg string) Option
- func WithRetryable(status bool) Option
- func WithStatusCode(statusCode int) Option
- func WithTag(tag ...string) Option
- func WithTranslation(lang, message string) Option
- type Set
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrCatalogErrorNotFound is returned when a custom error isn't found in // the catalog. ErrCatalogErrorNotFound = NewNotFoundError("error", WithErrorCode("CE_ERR_CATALOG_ERR_NOT_FOUND")) // ErrCatalogInvalidName is returned when a catalog name is invalid. ErrCatalogInvalidName = NewInvalidError("name", WithErrorCode("CE_ERR_CATALOG_INVALID_NAME")) // ErrErrorCodeInvalidCode is returned when an error code is invalid. ErrErrorCodeInvalidCode = NewInvalidError("error code. It requires typeOf, and subject", WithErrorCode("CE_ERR_INVALID_ERROR_CODE")) // ErrorCodeRegex is a regular expression to validate error codes. It's // designed to match four distinct patterns: // // 1. An optional number and letter followed by an underscore, "ERR_", a // letter and a number, another underscore, another letter and a number, and // an optional underscore followed by a number and a letter: // Format: {optional_number_letter}_ERR_{number_letter}_{number_letter}_{optional_number_letter} // Example: 1A_ERR_A1_B2 or 1A_ERR_A1_B2_3C // // 2. "ERR_" followed by a letter and a number, another underscore, another // letter and a number, and an optional underscore followed by a number and // a letter: // Format: ERR_{number_letter}_{number_letter}_{optional_number_letter} // Example: ERR_A1_B2 or ERR_A1_B2_3C // // 3. "E" followed by 1 to 8 digits: // Format: E{1 to 8 digits} // Example: E12345678 // // 4. At least one letter or number (any combination of uppercase and // lowercase letters and digits): // Format: {letters or digits, at least one character} // Example: AbCd123. ErrorCodeRegex = regexp.MustCompile(`^(\d?[A-Za-z]_)?ERR_[A-Za-z]\d_[A-Za-z]\d(_\d[A-Za-z])?$|^ERR_[A-Za-z]\d_[A-Za-z]\d(_\d[A-Za-z])?$|^E\d{1,8}$|[A-Za-z\d]+`) )
var ( // ErrInvalidLanguageCode is returned when a language code is invalid. ErrInvalidLanguageCode = NewInvalidError("it must be a string, two-letter lowercase ISO 639-1 code OR two-letter lowercase ISO 639-1 code followed by an optional hyphen AND a two-letter uppercase ISO 3166-1 alpha-2 country code", WithErrorCode("CE_ERR_INVALID_LANG_CODE")) // ErrInvalidLanguageErrorMessage is returned when an error message is invalid. ErrInvalidLanguageErrorMessage = NewInvalidError("it must be a string, at least 3 characters long", WithErrorCode("CE_ERR_INVALID_LANG_ERROR_MESSAGE")) // ErrInvalidLanguageMessageMap is returned when a LanguageMessageMap is // invalid. ErrInvalidLanguageMessageMap = NewInvalidError("it must be a non-nil map of language codes to error messages", WithErrorCode("CE_ERR_INVALID_LANGUAGE_MESSAGE_MAP")) // BuiltInLanguages is a list of built-in prefixes languages. BuiltInLanguages = []string{ Chinese.String(), English.String(), French.String(), German.String(), Italian.String(), Portuguese.String(), Spanish.String(), } // LanguageRegex is a regular expression to validate language codes based on // ISO 639-1 and ISO 3166-1 alpha-2. LanguageRegex = regexp.MustCompile("^[a-z]{2}(-[A-Z]{2})?$|default") )
var ( // ErrTemplateNotFound is returned when a requested error template is not // found in the map. ErrTemplateNotFound = NewNotFoundError(fmt.Sprintf( "%s. %s. Built-in languages: %s.", "template", "Please set one using `SetErrorPrefixMap`", strings.Join(BuiltInLanguages, ", "), ), WithErrorCode("CE_ERR_TEMPLATE_NOT_FOUND")) // ErrLanguageNotFound is returned when a requested language is not supported. ErrLanguageNotFound = NewNotFoundError("language. Please set one using `SetErrorPrefixMap`", WithErrorCode("CE_ERR_LANGUAGE_NOT_FOUND")) )
Singleton variables and error instances.
Functions ¶
func AddNewLanguage ¶ added in v1.2.6
func AddNewLanguage( language string, errorTypePrefixTemplateMap ErrorPrefixMap, ) error
AddNewLanguage allows setting a new language to the error handling system, seeting the built-in error templates for each error type.
func From ¶ added in v1.2.8
From modifies the error with the given options, if `err` isn't a custom error it then returns a new custom error with the given options.
func GetTemplate ¶ added in v1.0.18
GetTemplate retrieves the error template for a specific language and error type. It returns an error if either the language or the template is not found.
func IsCustomError ¶ added in v1.2.2
IsCustomError checks if the error is a `CustomError`.
func IsErrorCode ¶ added in v1.2.3
IsErrorCode checks if the error is a `CustomError` with the specified code.
func IsHTTPStatus ¶ added in v1.2.3
IsHTTPStatus checks if the error is a `CustomError` with the specified HTTP status code.
func IsRetryable ¶ added in v1.2.3
IsRetryable checks if the error is a retryable `CustomError`.
func MustAddNewLanguage ¶ added in v1.2.6
func MustAddNewLanguage( language string, errorTypePrefixTemplateMap ErrorPrefixMap, )
MustAddNewLanguage is a wrapper around AddNewLanguage that panics if an error occurs.
func New ¶
New creates a new validated custom error returning it as en `error`.
Example ¶
Demonstrates how to create static, and dynamic custom errors, also how to check, and instrospect custom errors.
// Custom static error definition. ErrMissingID := NewMissingError("id", WithErrorCode("E1010")) // Some function, for demo purpose. SomeFunc := func(id string) error { if id == "" { // Usage of the custom static error. return ErrMissingID } // Dynamic custom error. return NewFailedToError("write to disk", WithErrorCode("E1523")) } // Case: Without `id`, returns `ErrMissingID`. if err := SomeFunc(""); err != nil { fmt.Println(errors.Is(err, ErrMissingID)) // true var cE *CustomError if errors.As(err, &cE) { fmt.Println(cE.StatusCode) // 400 } fmt.Println(err) // E1010: missing id (400 - Bad Request) } // Case: With `id`, returns dynamic error. if err := SomeFunc("12345"); err != nil { var cE *CustomError if errors.As(err, &cE) { fmt.Println(cE.StatusCode) // 500 } fmt.Println(err) // E1523: failed to write to disk (500 - Internal Server Error) }
Output: true 400 E1010: missing id 500 E1523: failed to write to disk
Example (I18n) ¶
ExampleNew_i18n demonstrates how to create an error catalog with translations and how to throw errors in different languages.
SEE: `i18n.md` file for more information.
////// // The following, is usually defined in the `errorcatalog.go` file. ////// const ( ////// // Define the error code constant. It helps to identify the error in // systems like Elasticsearch, Splunk and Datadog. It also helps to // maintain consistency across the application. ////// ErrInvalidHardDrivePath = "ERR_INVALID_HARD_DRIVE_PATH" ) // Create the application error catalog. catalog := MustNewCatalog("myIncredibleApp"). // Add errors by their constant error codes while setting up the // translations. For Spanish and French, it uses the built-in list of // common languages instead of hardcoding the language. // // NOTE: For supported built-in languages, the default word(s) used by // the built-in error functions (example: `NewFailedToError`), are // automatically translated and included in the message. // // SEE: `languages.go` file an up-to-date list of the supported built-in // list of languages. // // For ANY other language there are two options: // 1. Don't use the built-in functions but instead use the `New` function // and write the message in full, for example: "invalid hard drive path". // 2. Setup the language (see `ExampleNew_i18nSetupNewLang`). // // Reason: It's impossible for any package to cover all the possible // languages, combinations, and their translations. // // No need to add the "invalid" word. MustSet(ErrInvalidHardDrivePath, "hard drive path", // No need to add the "invalid" word. WithTranslation(Spanish.String(), "ruta de disco duro"), // No need to add the "invalid" word. WithTranslation(French.String(), "chemin de disque dur"), ) ////// // The following, from anywhere in the application. ////// // Retrieve the error from the catalog. err := catalog.MustGet(ErrInvalidHardDrivePath) // Throw that in the Spanish language as an and using the built-in // `InvalidError` function which automatically sets the HTTP status code to // `StatusBadRequest`. The language is specified by using the built-in list // of languages. The default "invalid" word is automatically translated. // // SEE: `languages.go` file for the list of languages. fmt.Println(err.NewInvalidError(WithLanguage(Spanish.String()))) // The same, but in French. fmt.Println(err.NewInvalidError(WithLanguage(French.String()))) // The same, standard way - in English. fmt.Println(err.NewInvalidError())
Output: ruta de disco duro inválido chemin de disque dur invalide invalid hard drive path
Example (I18nSetupNewLang) ¶
ExampleNew_i18n demonstrates how to create an error catalog with translations how to throw errors in different languages, and how to setup a new language.
SEE: `i18n.md` file for more information.
////// // The following, is usually defined in the `errorcatalog.go` file. ////// // Define a constant for the new language, to help with consistency. const Japanase = "jp" // Let's pretend that beyond English, Spanish, and French, the // application must support Japanese. In this case, Japanase is not part // of the built-in list of languages. We start by setting up the language, // and the respective built-in functions error messages. // // NOTE: MustAddNewLanguage properly updates the internal, package-level, // singleton. // // WARN: If you use `MustAddNewLanguage`, and specify an invalid language // such as "asd", it will panic! The language must be a valid ISO 639-1 or // ISO 3166-1 alpha-2. MustAddNewLanguage("jp", NewErrorPrefixMap( // "failed to" template. "%s に失敗しました", // "invalid" template. "%s が無効です", // "missing" template. "%s が見つかりません", // "required" template. "%s が必要です", // "not found" template. "%s が見つかりませんでした", )) const ( ////// // Define the error code constant. It helps to identify the error in // systems like Elasticsearch, Splunk and Datadog. It also helps to // maintain consistency across the application. ////// ErrInvalidHardDrivePath = "ERR_INVALID_HARD_DRIVE_PATH" ) // Create the application error catalog. catalog := MustNewCatalog("myIncredibleApp"). // Add errors by their constant error codes while setting up the // translations. For Spanish and French, it uses the built-in list of // common languages instead of hardcoding the language. // // NOTE: For supported built-in languages, the default word(s) used by // the built-in error functions (example: `NewFailedToError`), are // automatically translated and included in the message. // // SEE: `languages.go` file an up-to-date list of the supported built-in // list of languages. // // For ANY other language there are two options: // 1. Don't use the built-in functions but instead use the `New` function // and write the message in full, for example: "invalid hard drive path". // 2. Setup the language (see `ExampleNew_i18nSetupNewLang`). // // Reason: It's impossible for any package to cover all the possible // languages, combinations, and their translations. // // No need to add the "invalid" word. MustSet(ErrInvalidHardDrivePath, "hard drive path", // No need to add the "invalid" word. WithTranslation(Spanish.String(), "ruta de disco duro"), // No need to add the "invalid" word. WithTranslation(French.String(), "chemin de disque dur"), // Added support, no need to add the "invalid" word. WithTranslation("jp", "ハードドライブのパス"), ) // Retrieve the error from the catalog. err := catalog.MustGet(ErrInvalidHardDrivePath) // Throw that in the Spanish language as an and using the built-in // `InvalidError` function which automatically sets the HTTP status code to // `StatusBadRequest`. The language is specified by using the built-in list // of languages. The default "invalid" word is automatically translated. // // SEE: `languages.go` file for the list of languages. fmt.Println(err.NewInvalidError(WithLanguage(Spanish.String()))) // The same, but in French. fmt.Println(err.NewInvalidError(WithLanguage(French.String()))) // The same, but in Japanese. fmt.Println(err.NewInvalidError(WithLanguage(Japanase))) // The same, standard way - in English. fmt.Println(err.NewInvalidError())
Output: ruta de disco duro inválido chemin de disque dur invalide ハードドライブのパス が無効です invalid hard drive path
Example (Is) ¶
Demonstrates error chain. `errB` will wrap `errA` and will be considered the same by propagating the chain.
errA := NewMissingError("id") errB := NewMissingError("name", WithError(errA)) fmt.Println(errors.Is(errB, errA))
Output: true
Example (MarshalJSON) ¶
Demonstrates JSON marshalling of custom errors.
// New buffer string. var buf strings.Builder errA := NewMissingError("id") errB := NewMissingError("name", WithError(errA)) if err := json.NewEncoder(&buf).Encode(errB); err != nil { panic(err) } fmt.Println(strings.Contains(buf.String(), `message":"missing name. Original Error: missing id`))
Output: true
Example (NewFactory) ¶
ExampleNew_NewFactory demonstrates the usage of the NewFactory function.
factory := Factory( "id", WithFields(map[string]interface{}{ "test1": "test2", "test3": "test4", }), WithTag("testTag1", "testTag2", "testTag3"), ) childFactory := factory.NewChildError( WithFields(map[string]interface{}{ "test1": "test2", "test5": "test6", }), WithTag("testTag2", "testTag3", "testTag4"), ) // Write to a buffer and check the output. var buf bytes.Buffer fmt.Fprint(&buf, childFactory.NewMissingError()) fmt.Fprint(&buf, childFactory.NewFailedToError()) fmt.Fprint(&buf, childFactory.NewInvalidError()) fmt.Fprint(&buf, childFactory.NewRequiredError()) fmt.Fprint(&buf, childFactory.NewHTTPError(400)) finalMessage := buf.String() missing := checkIfStringContainsMany( finalMessage, "missing id", "failed to id", "invalid id", "missing id", "id required", "bad request", "Tags:", "Fields:", "testTag1", "testTag2", "testTag3", "testTag4", "test1=test2", "test3=test4", "test5=test6", ) if len(missing) == 0 { fmt.Println(true) } else { fmt.Println(missing) }
Output: true
Example (NewHTTPError) ¶
Demonstrates the NewHTTPError custom error.
fmt.Println(NewHTTPError(http.StatusNotFound).(*CustomError).APIError()) fmt.Println(NewHTTPError(http.StatusNotFound).(*CustomError).Error()) fmt.Println(NewHTTPError(http.StatusNotFound))
Output: not found (404 - Not Found) not found not found
Example (NewNoMessage) ¶
Demonstrates errors without message but with status code.
fmt.Println(New("", WithStatusCode(http.StatusAccepted))) fmt.Println(New("", WithStatusCode(http.StatusAccepted), WithErrorCode("E1010"))) fmt.Println(New("", WithStatusCode(http.StatusAccepted)).(*CustomError).APIError()) fmt.Println(New("", WithStatusCode(http.StatusAccepted), WithErrorCode("E1010")).(*CustomError).APIError()) fmt.Println(New("", WithErrorCode("E1010"))) fmt.Println(New("", WithErrorCode("E1010"), WithStatusCode(http.StatusAccepted))) fmt.Println(New("", WithErrorCode("E1010")).(*CustomError).APIError()) fmt.Println(New("", WithErrorCode("E1010"), WithStatusCode(http.StatusAccepted)).(*CustomError).APIError())
Output: Accepted E1010: Accepted Accepted (202) E1010: Accepted (202) E1010 E1010: Accepted E1010 E1010: Accepted (202)
Example (NewRetryableError) ¶
ExampleNew_Retryable error and SetRetried function. In this example the go go-resiliency/retrier package will be used, but any other retry package should work as well. Additionally, the example demonstrates how to check if the error is retryable, if it has a specific error code, if it has a specific HTTP status code, and if it is a custom error.
// Create a custom retryable error. retryableCE := NewFailedToError( "write to disk", WithErrorCode("E1523"), WithRetryable(true), ) // Initialize a retrier with exponential backoff strategy. r1 := retrier.New( retrier.ConstantBackoff(1, 300*time.Millisecond), CustomClassifier{}, ) // Execute the request with retry logic. if err := r1.Run(func() error { // Throw the retryable error. return retryableCE }); err != nil { fmt.Println(err) } fmt.Println(IsRetryable(retryableCE)) fmt.Println(IsErrorCode(retryableCE, "E1523")) fmt.Println(IsHTTPStatus(retryableCE, http.StatusInternalServerError)) fmt.Println(IsCustomError(retryableCE)) if toCE, ok := To(retryableCE); ok { fmt.Println(toCE.StatusCode) }
Output: E1523: failed to write to disk. Retryable: true. Retried: true true true true true 500
Example (Options) ¶
Demonstrates how to create static, and dynamic custom errors, also how to check, and instrospect custom errors.
fmt.Println( NewMissingError("id", WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error"))).(*CustomError).APIError(), )
Output: E1010: missing id (406 - Not Acceptable). Original Error: some error
Example (OptionsWithField) ¶
Demonstrates the WithField option.
// Store message in a buf to be checked later. var buf strings.Builder fmt.Fprintln(&buf, NewMissingError( "id", WithTag("test1", "test2"), WithField("testKey1", "testValue1"), WithField("testKey2", "testValue2"), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), )) fmt.Fprintln(&buf, NewMissingError( "id", WithTag("test1", "test2"), WithField("testKey1", "testValue1"), WithField("testKey2", "testValue2"), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), ).(*CustomError).APIError()) fmt.Println(len(checkIfStringContainsMany( buf.String(), "E1010: missing id", "E1010: missing id (406 - Not Acceptable)", "Original Error: some error", "Tags: test1, test2", "Fields:", "testKey1=testValue1", "testKey2=testValue2", )) == 0)
Output: true
Example (OptionsWithFields) ¶
Demonstrates the WithFields option.
// Store message in a buf to be checked later. var buf strings.Builder fmt.Fprintln(&buf, NewMissingError( "id", WithTag("test1", "test2"), WithFields(map[string]interface{}{ "testKey1": "testValue1", "testKey2": "testValue2", }), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), )) fmt.Fprintln(&buf, NewMissingError( "id", WithTag("test1", "test2"), WithFields(map[string]interface{}{ "testKey1": "testValue1", "testKey2": "testValue2", }), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), ).(*CustomError).APIError()) fmt.Println(len(checkIfStringContainsMany( buf.String(), "E1010: missing id", "E1010: missing id (406 - Not Acceptable)", "Original Error: some error", "Tags: test1, test2", "Fields:", "testKey1=testValue1", "testKey2=testValue2", )) == 0)
Output: true
Example (OptionsWithIgnoreIf) ¶
Demonstrates the WithIgnoreFunc option.
fmt.Println(NewMissingError("id", WithIgnoreFunc(func(cE *CustomError) bool { return strings.Contains(cE.Message, "id") })) == nil)
Output: true
Example (OptionsWithIgnoreString) ¶
Demonstrates the WithIgnoreString option.
fmt.Println(NewMissingError("id", WithIgnoreString("id")) == nil) fmt.Println(NewMissingError("id", WithError(errors.New("hehehe")), WithIgnoreString("hehehe")) == nil) fmt.Println(NewMissingError("id", WithIgnoreString("hahaha")) == nil)
Output: true true false
Example (OptionsWithTag) ¶
Demonstrates the WithTag option.
fmt.Println(NewMissingError( "id", WithTag("test1", "test2"), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), )) fmt.Println(NewMissingError( "id", WithTag("test1", "test2"), WithErrorCode("E1010"), WithStatusCode(http.StatusNotAcceptable), WithError(errors.New("some error")), ).(*CustomError).APIError())
Output: E1010: missing id. Original Error: some error. Tags: test1, test2 E1010: missing id (406 - Not Acceptable). Original Error: some error. Tags: test1, test2
func NewFailedToError ¶
NewFailedToError is the building block for errors usually thrown when some action failed, e.g: "Failed to create host". Default status code is `500`.
NOTE: Status code can be redefined, call `SetStatusCode`.
func NewHTTPError ¶ added in v1.0.7
NewHTTPError is the building block for simple HTTP errors, e.g.: Not Found.
func NewInvalidError ¶
NewInvalidError is the building block for errors usually thrown when something fail validation, e.g: "Invalid port". Default status code is `400`.
NOTE: Status code can be redefined, call `SetStatusCode`.
func NewMissingError ¶
NewMissingError is the building block for errors usually thrown when required information is missing, e.g: "Missing host". Default status code is `400`.
NOTE: Status code can be redefined, call `SetStatusCode`.
func NewNotFoundError ¶ added in v1.0.18
NewNotFoundError is the building block for errors usually thrown when something is not found, e.g: "Host not found". Default status code is `400`.
NOTE: Status code can be redefined, call `SetStatusCode`.
func NewRequiredError ¶
NewRequiredError is the building block for errors usually thrown when required information is missing, e.g: "Port is required". Default status code is `400`.
NOTE: Status code can be redefined, call `SetStatusCode`.
Types ¶
type Catalog ¶ added in v1.0.18
type Catalog struct { // CustomErrors are the errors in the catalog. ErrorCodeErrorMap ErrorCodeErrorMap `json:"custom_errors"` // Name of the catalog, usually, the name of the application. Name string `json:"name" validate:"required,gt=3"` }
Catalog contains a set of errors (customerrors).
func MustNewCatalog ¶ added in v1.1.4
MustNewCatalog creates a new Catalog. If an error occurs, panics.
func NewCatalog ¶ added in v1.0.18
NewCatalog creates a new Catalog.
func (*Catalog) Get ¶ added in v1.0.18
func (c *Catalog) Get(errorCode string, _ ...Option) (*CustomError, error)
Get returns a custom error from the catalog, if not found, returns an error.
func (*Catalog) MustGet ¶ added in v1.0.18
func (c *Catalog) MustGet(errorCode string, opts ...Option) *CustomError
MustGet returns a custom error from the catalog, if not found, panics.
type CustomError ¶
type CustomError struct { // Code can be any custom code, e.g.: E1010. Code string `json:"code,omitempty" validate:"omitempty,gte=2"` // Err optionally wraps the original error. Err error `json:"-"` // Field enhances the error message with more structured information. Fields *sync.Map `json:"fields,omitempty"` // Human readable message. Minimum length: 3. Message string `json:"message" validate:"required,gte=3"` // Message in different languages. LanguageMessageMap LanguageMessageMap `json:"languageMessageMap"` // LanguageErrorTypeMap is a map of language prefixes to templates such // as "missing %s", "%s required", "%s invalid", etc. LanguageErrorTypeMap LanguageErrorMap `json:"languageErrorTypeMap"` // Retryable indicates if the error is retryable. Retryable bool `json:"retryable"` // Retried indicates if the error has been retried. Retried bool `json:"retried"` // StatusCode is a valid HTTP status code, e.g.: 404. StatusCode int `json:"-" validate:"omitempty,gte=100,lte=511"` // Tags is a SET of tags which helps to categorize the error. Tags *Set `json:"tags,omitempty"` // contains filtered or unexported fields }
CustomError is the base block to create custom errors. It provides context - a `Message` to an optional `Err`. Additionally a `Code` - for example "E1010", and `StatusCode` can be provided.
func Copy ¶ added in v1.0.18
func Copy(src, target *CustomError) *CustomError
Copy performs a deep copy of the src CustomError into the target CustomError. It ensures that all fields, including nested structures like maps and sets, are properly copied. This function is useful when you need to create a new CustomError instance based on an existing one, while avoiding any shared references to mutable fields.
func Factory ¶ added in v1.0.18
func Factory(message string, opts ...Option) *CustomError
Factory creates a validated and pre-defined error to be recalled and thrown later, with or without options. Possible options are: - `NewFailedToError` - `NewInvalidError` - `NewMissingError` - `NewRequiredError` - `NewHTTPError`.
func To ¶ added in v1.2.4
func To(err error) (*CustomError, bool)
To converts the error to a `CustomError`.
func (*CustomError) APIError ¶
func (cE *CustomError) APIError() string
APIError is like error plus status code information.
func (*CustomError) Error ¶
func (cE *CustomError) Error() string
Error interface implementation returns the properly formatted error message. It will contain `Code`, `Tags`, `Fields` and any wrapped error.
func (*CustomError) FormatError ¶ added in v1.2.4
func (cE *CustomError) FormatError(errorType string, opts ...Option) *CustomError
FormatError formats the error message with the given error type.
func (*CustomError) Is ¶
func (cE *CustomError) Is(err error) bool
Is interface implementation ensures chain continuity. Treats `CustomError` as equivalent to `err`.
func (*CustomError) JustError ¶ added in v1.0.16
func (cE *CustomError) JustError() string
JustError returns the error message without any additional information.
func (*CustomError) MarshalJSON ¶ added in v1.0.6
func (cE *CustomError) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface.
SEE https://gist.github.com/thalesfsp/3a1252530750e2370345a2418721ff54
func (*CustomError) New ¶ added in v1.0.18
func (cE *CustomError) New(opts ...Option) error
New is the building block for other errors. Preferred method to be used for translations (WithLanguage).
func (*CustomError) NewChildError ¶ added in v1.0.14
func (cE *CustomError) NewChildError(opts ...Option) *CustomError
NewChildError creates a new `CustomError` with the same fields and tags of the parent `CustomError` plus the new fields and tags passed as arguments.
func (*CustomError) NewFailedToError ¶ added in v1.0.14
func (cE *CustomError) NewFailedToError(opts ...Option) error
NewFailedToError is the building block for errors usually thrown when some action failed, e.g: "Failed to create host". Default status code is `500`.
NOTE: Preferably don't use with the `WithLanguage` because of the "Failed to" part. Prefer to use `New` instead.
NOTE: Status code can be redefined, call `SetStatusCode`.
func (*CustomError) NewHTTPError ¶ added in v1.0.14
func (cE *CustomError) NewHTTPError(statusCode int, opts ...Option) error
NewHTTPError is the building block for simple HTTP errors, e.g.: Not Found.
NOTE: `WithLanguage` has no effect on it because of it's just a simple HTTP error.
NOTE: Status code can be redefined, call `SetStatusCode`.
func (*CustomError) NewInvalidError ¶ added in v1.0.14
func (cE *CustomError) NewInvalidError(opts ...Option) error
NewInvalidError is the building block for errors usually thrown when something fail validation, e.g: "Invalid port". Default status code is `400`.
NOTE: Preferably don't use with the `WithLanguage` because of the "Invalid" part. Prefer to use `New` instead.
NOTE: Status code can be redefined, call `SetStatusCode`.
func (*CustomError) NewMissingError ¶ added in v1.0.14
func (cE *CustomError) NewMissingError(opts ...Option) error
NewMissingError is the building block for errors usually thrown when required information is missing, e.g: "Missing host". Default status code is `400`.
NOTE: Preferably don't use with the `WithLanguage` because of the "Missing" part. Prefer to use `New` instead.
NOTE: Status code can be redefined, call `SetStatusCode`.
func (*CustomError) NewRequiredError ¶ added in v1.0.14
func (cE *CustomError) NewRequiredError(opts ...Option) error
NewRequiredError is the building block for errors usually thrown when required information is missing, e.g: "Port is required". Default status code is `400`.
NOTE: Preferably don't use with the `WithLanguage` because of the "Required" part. Prefer to use `New` instead.
NOTE: Status code can be redefined, call `SetStatusCode`.
func (*CustomError) SetMessage ¶ added in v1.0.18
func (cE *CustomError) SetMessage(message string)
SetMessage sets the message of the error.
func (*CustomError) SetRetried ¶ added in v1.2.2
func (cE *CustomError) SetRetried(status bool)
SetRetried sets if the error has been retried.
func (*CustomError) Unwrap ¶
func (cE *CustomError) Unwrap() error
Unwrap interface implementation returns inner error.
type ErrorCode ¶ added in v1.0.18
type ErrorCode string
ErrorCode is the consistent way to express an error. Despite there's no enforcement, it's recommended that to be meanginful, all upper cased and separated by underscore, example: "INVALID_REQUEST".
func NewErrorCode ¶ added in v1.0.18
NewErrorCode creates a new ErrorCode. It will be validated and stored upper cased.
type ErrorCodeErrorMap ¶ added in v1.0.18
ErrorCodeErrorMap is a map of error codes to custom errors.
type ErrorPrefixMap ¶ added in v1.0.18
ErrorPrefixMap is a thread-safe map storing error prefix templates for different error types.
func NewErrorPrefixMap ¶ added in v1.0.18
func NewErrorPrefixMap( failedToTemplate, invalidTemplate, missingTemplate, requiredTemplate, notFoundTemplate string, ) ErrorPrefixMap
NewErrorPrefixMap creates a new ErrorPrefixMap with the provided templates for each error type. This function is useful when setting up custom error templates for a new language.
type ErrorType ¶ added in v1.0.18
type ErrorType string
ErrorType represents the category or nature of an error.
const ( FailedTo ErrorType = "failed to" // Indicates a failure to perform an action Invalid ErrorType = "invalid" // Denotes an invalid input or state Missing ErrorType = "missing" // Signifies a missing required element NotFound ErrorType = "not found" // Indicates that a requested resource was not found Required ErrorType = "required" // Denotes a required element that was not provided )
These are the built-in languages supported by the error handling system, and their respective default error message.
type Language ¶ added in v1.0.18
type Language string
Language is a language code.
func NewLanguage ¶ added in v1.0.18
NewLanguage creates a new Lang.
func (Language) GetRoot ¶ added in v1.0.18
GetRoot returns the root language code. Given "en-US", it returns "en".
type LanguageErrorMap ¶ added in v1.0.18
LanguageErrorMap is a thread-safe map storing error templates for different languages.
func GetLanguageErrorMap ¶ added in v1.0.18
func GetLanguageErrorMap() LanguageErrorMap
GetLanguageErrorMap returns the singleton instance of LanguageErrorMap. It initializes the map with built-in languages and their respective error templates.
func GetLanguageErrorTypeMap ¶ added in v1.0.18
func GetLanguageErrorTypeMap(language string) (LanguageErrorMap, error)
GetLanguageErrorTypeMap retrieves the ErrorPrefixMap for a specific language. It returns an error if the language is not supported.
type LanguageMessageMap ¶ added in v1.0.18
LanguageMessageMap is a map of language codes to error messages.
type Option ¶
type Option func(s *CustomError)
Option allows to define error options.
func WithErrorCode ¶ added in v1.2.0
WithErrorCode allows to specify an error code, such as "E1010".
func WithFields ¶ added in v1.0.15
WithFields allows to set fields for the error.
func WithIgnoreFunc ¶ added in v1.0.8
func WithIgnoreFunc(f func(cE *CustomError) bool) Option
WithIgnoreFunc ignores an error if the specified function returns true.
func WithIgnoreString ¶ added in v1.0.8
WithIgnoreString ignores an error if the error message, or the the underlying error message contains the specified string.
func WithLanguage ¶ added in v1.0.18
WithLanguage specifies the language for the error message. It requires `lang` to be a valid ISO 639-1 and ISO 3166-1 alpha-2 standard, and the `LanguageMessageMap` map to be set, otherwise it will be ignored returning the default message. If a language is specified in the "en-US" format, and not found, it will try to find by the root "en".
func WithMessage ¶ added in v1.0.18
WithMessage allows to specify the error message.
func WithRetryable ¶ added in v1.2.2
WithRetryable allows to specify if the error is retryable.
func WithStatusCode ¶
WithStatusCode allows to specify the status code, such as "200".
func WithTranslation ¶ added in v1.0.18
WithTranslation sets the translation for the error message.
NOTE: For supported built-in languages, the default word(s) used by the built-in error functions (example: `NewFailedToError`), are automatically translated and included in the message.
SEE: `languages.go` file an up-to-date list of the supported built-in list of languages.
For ANY other language there are two options: 1. Don't use the built-in functions but instead use the `New` function and write the message in full, for example: "invalid hard drive path". 2. Setup the language (see `ExampleNew_i18nSetupNewLang`).
Reason: It's impossible for any package to cover all the possible languages, combinations, and their translations.
SEE: `i18n.md` file for more information.