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. fmt.Errorf() / %w

fmt.Errorf() / %w

fmt.Errorf() creates a formatted error message. Using the %w verb, you can wrap an existing error to add context while preserving the original error information.

Syntax

import "fmt"

// Creates a formatted error.
err := fmt.Errorf("format", args...)

// Wraps an error with %w (makes it searchable with errors.Is / errors.As).
wrapped := fmt.Errorf("context info: %w", originalErr)

// Embeds an error message with %v (not wrapped, so errors.Is cannot find it).
notWrapped := fmt.Errorf("context info: %v", originalErr)

Difference between %w and %v

VerbDescription
%wWraps the error. The resulting error has an Unwrap() method, allowing errors.Is() and errors.As() to recursively search the original error.
%vEmbeds only the error's message string. No wrapping occurs, so errors.Is() cannot find the original error.
Error chainMultiple levels of wrapping are supported. errors.Is() traverses the entire chain to find a matching error.

Sample Code

package main

import (
    "errors"
    "fmt"
)

// Defines a sentinel error.
var ErrDatabase = errors.New("database error")

// A low-level function.
func queryDB(id int) error {
    if id <= 0 {
        return ErrDatabase
    }
    return nil
}

// A middle-layer function that adds context information.
func getUser(id int) error {
    if err := queryDB(id); err != nil {
        // Wraps with %w to build an error chain.
        return fmt.Errorf("getUser(id=%d): %w", id, err)
    }
    return nil
}

// A higher-layer function that wraps further.
func handleRequest(id int) error {
    if err := getUser(id); err != nil {
        return fmt.Errorf("handleRequest: %w", err)
    }
    return nil
}

func main() {
    err := handleRequest(-1)
    if err != nil {
        // Prints the full error message.
        fmt.Println(err)
        // Outputs: "handleRequest: getUser(id=-1): database error"

        // errors.Is() traverses the chain and finds ErrDatabase.
        if errors.Is(err, ErrDatabase) {
            fmt.Println("The root cause is a database error")
        }

        // errors.Unwrap() unwraps one level at a time.
        inner := errors.Unwrap(err)
        fmt.Println(inner) // Outputs: "getUser(id=-1): database error"

        inner2 := errors.Unwrap(inner)
        fmt.Println(inner2) // Outputs: "database error"
    }

    // %v does not wrap, so errors.Is() cannot find the original error.
    notWrapped := fmt.Errorf("failed: %v", ErrDatabase)
    fmt.Println(errors.Is(notWrapped, ErrDatabase)) // Outputs: "false"

    // %w wraps the error, so errors.Is() can find it.
    wrapped := fmt.Errorf("failed: %w", ErrDatabase)
    fmt.Println(errors.Is(wrapped, ErrDatabase)) // Outputs: "true"
}

Notes

Wrapping errors with %w is the standard Go approach for adding context — such as which function failed or what arguments were used — while still allowing callers to inspect the underlying error type. Reading the error message alone tells you the full path the error traveled.

Only one %w can be used in a single fmt.Errorf() call (Go 1.20 and later allow multiple, but it is best to stick to one to keep things simple).

Use errors.Is() / errors.As() to check errors. For attaching richer error information using custom error types, see Custom Error Types.

If you find any errors or copyright issues, please .