(feature added in Go 1.13)

This is an interesting feature, when building errors that contain other errors.

Unwrap is actually defined as follows:

func Unwrap(err error) error {

	u, ok := err.(interface {
		Unwrap() error
	if !ok {
		return nil
	return u.Unwrap()


It first checks whether err has itself the Unwrap method. If it doesn't, then nothing else can be done. There is nothing to unwrap. Nada. But if the method is defined, it calls it and returns its value, which is an error itself.

This is a very useful way of composing errors, and thus adding much more information. We could think of the following scenario:

package main

import (
type databaseError struct {
    err error

type queryMissingParamsError struct {
    params string

func (de *databaseError) Unwrap() error {
    return de.err

func (de *databaseError) Error() string {
    return fmt.Sprintf("Database error. %s", de.err)

func (qmp *queryMissingParamsError) Error() string {
    return fmt.Sprintf("Some parameter were missing: %s", qmp.params)

// bogus query
type Query struct {}

func (q *Query) Check() error {
    return &databaseError {
        err: &queryMissingParamsError {
            params: "name",

func handleDatabaseQuery(query *Query) error {
    err := query.Check()
    if err == nil {
        return nil
    return errors.Unwrap(err)
func main() {
	q := &Query{}
	err := handleDatabaseQuery(q)

In this example, we can see how an error can pack and unpack other errors. And we can choose to define a strategy for the different scenarios. So, in this particular example, we could ask the user to make the query again and remind her not to forget to include name as a paramter.