The %w directive wraps an existing error while preserving the original error for later inspection. It is useful when adding context, marking an error, or doing both. section 7.2
Add context without losing the cause
if err != nil { return fmt.Errorf("bar failed: %w", err) } Unlike %v, which formats the error message and discards the source-error relationship, %w keeps the wrapped error available to callers. section 7.2
Wrapping also changes how callers must check errors. A direct type switch sees only the outer formatted error, so a refactoring that adds %w can make an existing type check fail. Use errors.As to find a wrapped error type and errors.Is to compare a wrapped error value. section 7.3 section 7.8
Preserve transient-error handling
if err != nil { return 0, fmt.Errorf("failed to get transaction %s: %w", transactionID, err) } if errors.As(err, &transientError{}) { http.Error(w, err.Error(), http.StatusServiceUnavailable) } else { http.Error(w, err.Error(), http.StatusBadRequest) } section 7.3
Use %w when callers should retain access to the cause; return the error directly when no context or classification is needed. Avoid wrapping when exposing the source error would create unwanted coupling. section 7.2 section 7.8
if err != nil {
return fmt.Errorf("bar failed: %w", err)
}
Inspect the compact implementation of contextual error wrapping with fmt.Errorf and %w. section 7.2

