Errors Direct Comparison
ID |
go.errors_direct_comparison |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Go |
Tags |
reliability, suspicious |
Description
Reports a direct == / != comparison between a local error variable and an error sentinel —
err == ErrNotFound. The idiomatic test is errors.Is(err, ErrNotFound).
Rationale
Comparing errors by identity breaks the moment an error is wrapped with
fmt.Errorf("…: %w", err): the wrapped value is no longer == the sentinel even though it
still is that error. errors.Is unwraps the chain before comparing, so it keeps working as
errors are wrapped and re-wrapped across call boundaries.
To stay free of false positives the rule relies on the universal Go naming conventions: one
operand must be a bare identifier named err, and the other a bare identifier that looks like an
exported sentinel (Err followed by an upper-case letter). Package-qualified sentinels such as
io.EOF are out of scope, and a nil comparison is never flagged.
if err == ErrNotFound { ... } // FLAW — use errors.Is(err, ErrNotFound)
if errors.Is(err, ErrNotFound) {} // OK
if err == nil { ... } // OK — nil check
if err == io.EOF { ... } // OK — package-qualified sentinel, out of scope