Is Checking Err == Nil Instead Of
Fast recall
Quick revision
Core answer
Practical understanding of If Err Not Nil Pattern.
Repeating a definition without saying when to use it.
Give one trade-off and say how you would test it.
Interview-ready guide
Interview answer
Pass-through and wrap are both returns, with different information outcomes:
// pass-through: caller sees the original error, unchanged
if err != nil {
return err
}
// wrap: the caller sees what YOU were doing when it failed
if err != nil {
return fmt.Errorf("load config %s: %w", path, err)
}The pass-through is honest when your function adds nothing: a thin delegation where the caller already knows the operation. Wrapping is the default whenever your layer knows something the error doesn't carry — which file, which step, which request — because the caller's debugging question is always 'doing WHAT when this failed?'
The %w is what makes wrapping safe: it preserves the causal chain, so errors.Is(err, os.ErrNotExist) still works through your added text. %v would embed the message but cut the chain — the caller could no longer match the underlying cause.
The anti-pattern to name: wrapping with no information. fmt.Errorf("failed: %w", err) adds five characters and zero meaning — every layer doing it stacks 'failed: failed: failed:' around the real message. Wrap when there's something to say; pass through when there isn't.
Is Checking Err == Nil Instead Of
Direct Answer
Returning err passes it up unchanged; fmt.Errorf with %w adds context while keeping errors.Is/As working. Wrap when you add meaning; pass through when you add nothing.
Deep Dive & Architecture
The choice is really about WHERE the reader's attention lands when something fails. A returned error's message chain reads top-down: the outermost wrap is the operation the caller attempted; each inner layer adds the context that layer had. That narrative structure is why wrapping with the right local facts is the default:
// reads: 'start server: listen :8080: address already in use'
return fmt.Errorf("start server: %w", err)
versus passing raw, where the caller sees only 'address already in use' with no hint of what was being attempted. Same failure, different debugging cost.
The over-wrap anti-pattern has a signature: wrap messages that are pure ceremony. 'failed:', 'error:', 'operation failed:' add zero facts and the stack reads 'failed: failed: failed: address already in use' — the reader strips them mentally. The test: if your wrap text isn't a noun phrase or a fact (a file name, an operation, a step), it doesn't earn the line.
%w vs %v in the wrap is the other half of the discipline: %w preserves the chain so callers can Is/As; %v prints the same text but amputates the inspectability. Since no tooling warns %v-that-should-be-%w, it's convention — write %w by default, and reserve %v for terminal human-only formatting at the top of the program where no code will inspect below.
Common Mistakes & Pitfalls
Repeating a definition without saying when to use it.
Check your understanding
Answer these without looking back at the article.
- What is If Err Not Nil Pattern, and when would you use it?
- When would you use If Err Not Nil Pattern in a real project?
- How would you compare If Err Not Nil Pattern with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.