← Back to Go Course | Chapter 9: Error Handling | Lesson 2 of 6

Custom Error Types

A custom error type is like designing your own error form with extra fields, so the code that receives it can read more than just a message -- it can check exactly what kind of problem happened.
Syntax
go
type NameError struct {
    Field type
}

func (e *NameError) Error() string {
    return "message"
}

Defining a Custom Error Type

A custom error is just a struct with an Error() string method, which lets it carry additional structured fields beyond a plain message -- useful when calling code needs more context than text alone.

Example: Defining a Custom Error Type

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// Define a struct type named ValidationError
type ValidationError struct {
	Field string
	Msg   string
}

// Define the method Error on type ValidationError
func (e *ValidationError) Error() string {
	// Sprintf builds a formatted string instead of printing it
	return fmt.Sprintf("%s: %s", e.Field, e.Msg)
}

// main is where the program starts running
func main() {
	var err error = &ValidationError{Field: "age", Msg: "must be positive"}
	// Print the values followed by a newline
	fmt.Println(err)
}

Returning a Custom Error

A function can return a custom error type through the standard error interface, so calling code that only cares whether it failed can treat it like any other error, while code that wants details can inspect it further.

Example: Returning a Custom Error

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// Define a struct type named OutOfStockError
type OutOfStockError struct {
	Item string
}

// Define the method Error on type OutOfStockError
func (e *OutOfStockError) Error() string {
	// Sprintf builds a formatted string instead of printing it
	return fmt.Sprintf("%s is out of stock", e.Item)
}

// Define the function checkStock
func checkStock(item string, qty int) error {
	// Check whether qty <= 0
	if qty <= 0 {
		// Send &OutOfStockError{Item: item} back to the caller
		return &OutOfStockError{Item: item}
	}
	return nil
}

func main() {
	if err := checkStock("widget", 0); err != nil {
		fmt.Println(err)
	}
}

Extracting a Custom Error with errors.As

errors.As checks whether an error (or anything it wraps) matches a specific custom error type, and if so, populates a target variable with it -- letting calling code react to structured fields, not just a message string.

Note: errors.As also unwraps any chain of wrapped errors to find a matching type.

Example: Extracting a Custom Error with errors.As

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the packages this program uses
import (
	"errors"
	"fmt"
)

// Define a struct type named OutOfStockError
type OutOfStockError struct {
	Item string
}

// Define the method Error on type OutOfStockError
func (e *OutOfStockError) Error() string {
	// Sprintf builds a formatted string instead of printing it
	return fmt.Sprintf("%s is out of stock", e.Item)
}

// main is where the program starts running
func main() {
	var err error = &OutOfStockError{Item: "widget"}

	// Declare oosErr with the zero value of its type
	var oosErr *OutOfStockError
	// Check whether errors.As(err, &oosErr)
	if errors.As(err, &oosErr) {
		fmt.Println("out of stock item:", oosErr.Item)
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Defining a custom error struct but forgetting to implement Error() string on it, so it doesn't actually satisfy the error interface.
  2. Using a value receiver for Error() but returning &MyError{} (a pointer) elsewhere inconsistently, causing type assertion mismatches.
  3. Storing only a string message in a custom error type when structured fields (like a status code) would let callers react programmatically.
Chapter Summary
  • A custom error type is any struct that implements the Error() string method.
  • Custom errors can carry structured data beyond a plain message, like an error code or the invalid value.
  • Callers use errors.As to check for and extract a specific custom error type.
  • Custom errors make failure handling more precise than parsing error message strings.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.