When handling failures, make error semantics explicit and consistent across the stack:
StatusCode in the caller; reserve parsing/”could not parse” errors for successful responses.fmt.Errorf) rather than introducing new error packages/types without an established convention.Example pattern (retry classification):
func isRetryableTransportError(err error) bool {
if err == nil {
return false
}
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
return true
}
var netErr net.Error
return errors.As(err, &netErr) && (netErr.Timeout() || netErr.Temporary())
}
And ensure callers only retry when the failure occurs before output is committed, with tests covering Timeout, Temporary, and the “neither set” negative case.
Enter the URL of a public GitHub repository