A sentinel error is a predefined error value representing an expected condition that callers may check. Define it as a package-level variable, conventionally beginning with Err, such as ErrFoo. Use sentinel values for expected outcomes; represent unexpected failures with specific error types. section 7.4
The comparison mistake
Direct comparison works only when the returned value is the sentinel itself: err == sql.ErrNoRows. If another function wraps that error with fmt.Errorf and %w, direct comparison fails even though the underlying condition remains sql.ErrNoRows. Use errors.Is(err, sql.ErrNoRows) when wrapping may occur. section 7.4 section 7.8
Choose the representation according to the meaning of the failure:
- Return a sentinel error for an expected condition, such as sql.ErrNoRows when a valid query returns no rows. section 7.4
- Use a specific error type for unexpected failures such as network or connection-polling errors. section 7.4
- Use errors.Is rather than == when the error may have been wrapped; compare an error type with errors.As. section 7.8
import "errors"
var ErrFoo = errors.New("foo")
Inspect the minimal declaration pattern for a sentinel error. section 7.4
err := query()
if err != nil {
if err == sql.ErrNoRows { #1
// ...
} else {
// ...
}
}
Compare a query error directly with sql.ErrNoRows when no wrapping is involved. section 7.4
err := query()
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
// ...
} else {
// ...
}
}
Preserve the sentinel check across wrapped errors with errors.Is. section 7.4


