Should You Check Err After Checking The
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
Check the error before anything else. The convention — on failure, other return values are zero/nil — means reading the result before the check reads garbage:
n, err := reader.Read(buf)
process(buf[:n]) // BUG on error: n is 0, or worse, stale
if err != nil {
return err
}The order matters because the zero-value convention makes the result slot meaningless when err is non-nil. buf[:0] processes nothing — silently, no error — or with a partially-filled buffer from a previous call, processes stale data. Either way the bug is invisible until you trace why 'nothing happened.'
The guard-first shape:
n, err := reader.Read(buf)
if err != nil {
return err
}
process(buf[:n]) // n is valid ONLY below the guardThe one documented exception: io.Reader's Read returns the count of bytes read before an error (including io.EOF) — data read before the failure is real, and callers should use it. That exception is famous BECAUSE it's the exception: everywhere else, the rule is absolute — err first, values after, never reversed.
Should You Check Err After Checking The
Direct Answer
Check err first. On failure, other returns are zero values — reading them before the check is the classic bug.
Deep Dive & Architecture
The convention — zero values on failure — is a contract between every function and every caller, and the classic bug is violating the READ ORDER of that contract. The canonical demonstration is buffered IO:
n, err := r.Read(buf)
total := n // BUG: captured before knowing if n is valid
if err != nil {
return total, err // returns a value the docs may not promise
}
On failure, n is 0 for a fresh reader — or, for some implementations, a partially-valid count that the docs say to use... or don't. The caller can't know which without reading the specific API. The convention resolves this: DON'T read other returns until err is nil, UNLESS the API explicitly documents partial results.
io.Reader's Read is the exception that defines the rule — 'n bytes were successfully read before the error' is a documented, universal behavior, and code that handles Read errors is EXPECTED to process buf[:n] first. That's why you see:
for {
n, err := r.Read(buf)
total += n // LEGAL here: Read documents n-before-err
if err != nil {
break // with the data already counted
}
}
The io.EOF convention (n>0 with err==io.EOF is legal, and the read loop processes the data THEN exits) makes streaming possible — every bufio and io.Copy depends on it. So the deep rule: check err first by default; read the API docs when the failure itself carries usable data; and io.Read/Write are the two families where partial-data-plus-error is contractual, not accidental.
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?
- How would you compare If Err Not Nil Pattern with an alternative?
- What is a common mistake when using If Err Not Nil Pattern?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.