Go error naming conventions

Declared error variables

Use a name with the prefix Err to name declared error variables. For example, ErrFormat. For their unexported counterparts use the prefix err. For example, errLongName.

var ErrFormat = errors.New("zip: not a valid zip file")
var errLongName = errors.New("zip: FileHeader.Name too long")

Declared error types

To name declared error types, use either the type name Error or a type name with the suffix Error.

package url // import "net/url"

type Error struct {
    Op  string
    URL string
    Err error
}

func (e *Error) Error() string
func (e *Error) Temporary() bool
/* ... more declarations elided ... */

Or as in:

package os // import "os"

type LinkError struct {
    Op  string
    Old string
    New string
    Err error
}

func (e *LinkError) Error() string
func (e *LinkError) Unwrap() error

Local assignment

For error variables in assignments in function scope, name the error variable err.

n, err := w.Write(p)
if err != nil {
    return err
}

Local assignment without shadowing

Sometimes you need to avoid shadowing an existing err. In such scenarios, name the second error variable err1, so that it doesn't shadow the previous error variable named err.

For examples, consider the following piece of code and the gofmt source.

// Write data, then close the writer. If both Write and Close
// fail, we want the Write error to take precedence over the Close error.
_, err := w.Write(data)
_, err1 := w.Close()
if err != nil {
    return err
}
return err1

The names cerr or c (short for "close error") are also acceptable here, instead of err1.

File scope assignment

If the assigned error variable is declared in file scope, use a more specific name, such as setupErr, to improve comprehension. For example:

package pax

var (
    once     sync.Once
    setupErr error
)

func setup() error { /* body elided */ }

func Create() error {
    once.Do(func() { setupErr = setup() })
    if setupErr != nil {
        return setupErr
    }
    // ... more code ...
}

func Read() error {
    once.Do(func() { setupErr = setup() })
    if setupErr != nil {
        return setupErr
    }
    // ... more code ...
}

Note that we do not want the names errSetup or setupError; these names conflict with scenarios 1 and 2, respectively.

Predeclared error type

Never shadow the predeclared identifier error which represents the built-in error interface.

f, error := os.Open("foo.txt") // BAD: DO NOT DO THIS.

Use a linter such as predeclared to prevent this.

errors.As variables

When using errors.As, name the target error variable <x>err where the placeholder <x> is the lowercased first character of the target error type.

For example, perr for PathError, as in:

var perr *fs.PathError
if errors.As(err, &perr) {
    log.Fatal(perr.Path)
}

Single character names such as e are also acceptable in this scenario, as in:

if err != nil {
    var e codeError
    if errors.As(err, &e) {
        os.Exit(e.code)
    } else {
        os.Exit(1)
    }
}

Do not reuse the variable name err.

Method receivers

Use one or two character-long names, as you typically would for a receiver name.

type MyError struct {}

func (m *MyError) Error() string

The names e or me are also appropriate for this example, but avoid names such as merr and myErr (both too lengthy) or err (confusing).

Named returns

In named returns, use the name err. Use documentation to discuss what the error represents.

func (c *Cbuf) Write(p []byte) (n int, err error)

A return name such as outerr is acceptable, too, if you are checking for an error in a deferred function or if you have several variables named err in the function body.