Middle · Go foundations

Errors are part of the API

Should every error be wrapped, logged and retried?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

EXAMPLE · FRAGMENT UNLESS A COMPLETE PROGRAM IS SHOWN

go
if errors.Is(err, context.DeadlineExceeded) {
    // Reconcile an unknown write outcome before retrying.
}
Reveal a strong answer
  1. Add context with fmt.Errorf and %w only when the cause is useful to callers; wrapping exposes matching behavior as part of the contract. errors.Is checks a target through the tree; errors.As extracts an assignable error type.

  2. Classify at a boundary: invalid input, not found, conflict, cancellation and transient dependency failure need different responses. A transport timeout can leave a remote write outcome unknown.

  3. Log once where ownership of handling ends, preserving request correlation and avoiding credentials. Retry only when the operation and budget allow it; wrapping or logging cannot make a non-idempotent action safe.

Common trap

Matching error strings is brittle; retrying every timeout can duplicate side effects.

Try it

A payment write times out after the server may have committed. What should the caller do?

Worked solution

Use an idempotency key or lookup by a stable operation ID to reconcile the outcome. Return a meaningful classification without inventing certainty. Test commit-then-disconnect, not just failure-before-write.

Change the constraint

How would joining multiple errors affect code that only calls Unwrap once?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-20. Use documentation for your pinned runtime, driver and tool version.