0
0
GoHow-ToBeginner · 3 min read

How to Unwrap Error in Go: Simple Guide with Examples

In Go, you can unwrap an error using the errors.Unwrap function, which returns the next error in the chain if the error wraps another. This helps you access the original error inside wrapped errors created with fmt.Errorf and the %w verb.
📐

Syntax

The errors.Unwrap function takes an error and returns the wrapped error inside it, or nil if there is none.

Usage pattern:

func Unwrap(err error) error

Here:

  • err is the error you want to unwrap.
  • The function returns the inner error wrapped by err, or nil if no wrapped error exists.
go
package main

import (
	"errors"
	"fmt"
)

func main() {
	var originalErr = errors.New("original error")
	wrappedErr := fmt.Errorf("wrapped: %w", originalErr)

	unwrappedErr := errors.Unwrap(wrappedErr)
	fmt.Println("Unwrapped error:", unwrappedErr)
}
Output
Unwrapped error: original error
💻

Example

This example shows how to create a wrapped error and then unwrap it to get the original error.

go
package main

import (
	"errors"
	"fmt"
)

func main() {
	// Create the original error
	originalErr := errors.New("file not found")

	// Wrap the original error with more context
	wrappedErr := fmt.Errorf("read config failed: %w", originalErr)

	// Unwrap to get the original error
	unwrappedErr := errors.Unwrap(wrappedErr)

	fmt.Println("Wrapped error:", wrappedErr)
	fmt.Println("Unwrapped error:", unwrappedErr)
}
Output
Wrapped error: read config failed: file not found Unwrapped error: file not found
⚠️

Common Pitfalls

One common mistake is trying to unwrap an error that is not wrapped, which returns nil. Also, unwrapping only goes one level deep, so to get the original error in a chain, you may need to unwrap repeatedly.

Another pitfall is using %v instead of %w when wrapping errors, which prevents unwrapping.

go
package main

import (
	"errors"
	"fmt"
)

func main() {
	originalErr := errors.New("network error")

	// Wrong wrapping: using %v does NOT wrap the error
	wrongWrap := fmt.Errorf("failed: %v", originalErr)

	// Correct wrapping: using %w wraps the error
	correctWrap := fmt.Errorf("failed: %w", originalErr)

	fmt.Println("Unwrap wrongWrap:", errors.Unwrap(wrongWrap))   // <nil>
	fmt.Println("Unwrap correctWrap:", errors.Unwrap(correctWrap)) // network error
}
Output
Unwrap wrongWrap: <nil> Unwrap correctWrap: network error
📊

Quick Reference

Tips for unwrapping errors in Go:

  • Use errors.Unwrap(err) to get the wrapped error.
  • Wrap errors with fmt.Errorf("%w") to enable unwrapping.
  • To check error chains, use errors.Is or errors.As for safer error handling.
  • Unwrapping only unwraps one level; loop if you need the root cause.

Key Takeaways

Use errors.Unwrap to get the inner error wrapped inside another error.
Wrap errors with fmt.Errorf and the %w verb to enable unwrapping.
Unwrap returns nil if the error does not wrap another error.
Unwrapping only goes one level deep; loop to reach the original error.
Use errors.Is and errors.As for common error checks in wrapped chains.