Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Go Dictionary
  3. Custom Error Types

Custom Error Types

A custom error type is created by implementing the Error() string method on a struct. Use this when you want an error to carry additional information, such as an error code or a field name.

Syntax

// Define a struct that implements the error interface.
type MyError struct {
    Field Type
}

// Implement the Error() string method. This satisfies the error interface.
func (e *MyError) Error() string {
    return "error message"
}

// Optionally implement Unwrap() to allow unwrapping the wrapped error.
func (e *MyError) Unwrap() error {
    return e.Cause
}

Implementation Patterns

PatternDescription
Implement Error() stringThe only requirement of the error interface. Any type with this method is automatically treated as an error.
Implement Unwrap() errorImplement this when wrapping another error. errors.Is() and errors.As() use this method to search the error chain.
Use with errors.As()Use errors.As(err, &target) to access a specific custom error type and retrieve its additional fields.
Pointer receiver vs. value receiverGenerally implement with a pointer receiver (*MyError). A value receiver also works, but be careful with nil pointer handling.

Sample Code

package main

import (
    "errors"
    "fmt"
)

// A custom error type representing an HTTP error.
type HTTPError struct {
    StatusCode int
    Message    string
    Cause      error // The wrapped underlying error.
}

// Implements the error interface.
func (e *HTTPError) Error() string {
    if e.Cause != nil {
        return fmt.Sprintf("HTTP %d: %s (caused by: %v)", e.StatusCode, e.Message, e.Cause)
    }
    return fmt.Sprintf("HTTP %d: %s", e.StatusCode, e.Message)
}

// Implements Unwrap() to support error chain traversal.
func (e *HTTPError) Unwrap() error {
    return e.Cause
}

// A custom error type representing a validation error.
type ValidationError struct {
    Field   string
    Value   any
    Message string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("validation failed on '%s' (value=%v): %s", e.Field, e.Value, e.Message)
}

// A function that processes a request.
func processRequest(userID int) error {
    if userID <= 0 {
        return &ValidationError{
            Field:   "userID",
            Value:   userID,
            Message: "must be a positive integer",
        }
    }
    if userID > 1000 {
        cause := errors.New("record not found in database")
        return &HTTPError{StatusCode: 404, Message: "user not found", Cause: cause}
    }
    return nil
}

func main() {
    // Example of a validation error.
    err := processRequest(-5)
    fmt.Println(err)
    // Prints: "validation failed on 'userID' (value=-5): must be a positive integer"

    // Use errors.As() to retrieve fields from the custom error type.
    var valErr *ValidationError
    if errors.As(err, &valErr) {
        fmt.Printf("Field: %s\n", valErr.Field)  // Prints: "Field: userID"
        fmt.Printf("Value: %v\n", valErr.Value)   // Prints: "Value: -5"
    }

    // Example of an HTTP error (with Unwrap support).
    err = processRequest(9999)
    fmt.Println(err)
    // Prints: "HTTP 404: user not found (caused by: record not found in database)"

    var httpErr *HTTPError
    if errors.As(err, &httpErr) {
        fmt.Printf("Status code: %d\n", httpErr.StatusCode) // Prints: "Status code: 404"
    }

    // errors.Is() can also search through unwrapped errors.
    dbErr := errors.New("record not found in database")
    wrapped := &HTTPError{StatusCode: 404, Message: "not found", Cause: dbErr}
    fmt.Println(errors.Is(wrapped, dbErr)) // Prints: "true"
}

Notes

A custom error type can hold structured details — such as a status code, field name, or original value — in addition to the error kind itself. Combined with errors.As(), callers can access these details directly.

Always create custom errors using a pointer to the type (*MyError). A value type (MyError) will work, but comparisons with nil may produce unexpected results.

For wrapping errors and adding context, you can also use fmt.Errorf() / %w. For information on how to inspect errors, see error type / errors package.

If you find any errors or copyright issues, please .