Documentation
¶
Overview ¶
Package errdefs provides behavior-based error classification.
Errors are classified by marker interfaces rather than error codes. Each category has three associated items:
- An unexported marker interface (e.g. interface{ NotFound() })
- A constructor that wraps/creates errors with the marker
- A check function (e.g. IsNotFound)
Sentinel errors remain plain stdlib errors; classification is orthogonal to identity — errors.Is checks identity, IsXxx checks category.
Index ¶
- Variables
- func Aborted(err error) error
- func Abortedf(format string, args ...any) error
- func BudgetExceeded(err error) error
- func BudgetExceededf(format string, args ...any) error
- func ClassifyHTTPStatus(provider string, code int, body string) error
- func ClassifyProviderError(provider string, err error) error
- func ClassifyStatus(status int, cause error) error
- func Conflict(err error) error
- func Conflictf(format string, args ...any) error
- func Fmt(format string, args ...any) error
- func Forbidden(err error) error
- func Forbiddenf(format string, args ...any) error
- func FromContext(err error) error
- func HTTPStatus(err error) int
- func HasClassification(err error) bool
- func Internal(err error) error
- func Internalf(format string, args ...any) error
- func Interrupted(err error) error
- func Interruptedf(format string, args ...any) error
- func IsAborted(err error) bool
- func IsBudgetExceeded(err error) bool
- func IsConflict(err error) bool
- func IsForbidden(err error) bool
- func IsInternal(err error) bool
- func IsInterrupted(err error) bool
- func IsNotAvailable(err error) bool
- func IsNotFound(err error) bool
- func IsPolicyDenied(err error) bool
- func IsRateLimit(err error) bool
- func IsTimeout(err error) bool
- func IsUnauthorized(err error) bool
- func IsValidation(err error) bool
- func New(text string) error
- func NotAvailable(err error) error
- func NotAvailablef(format string, args ...any) error
- func NotFound(err error) error
- func NotFoundf(format string, args ...any) error
- func ParseRetryAfter(value string) time.Duration
- func ParseRetryCount(value string) int
- func PolicyDenied(err error) error
- func PolicyDeniedf(format string, args ...any) error
- func RateLimit(err error) error
- func RateLimitf(format string, args ...any) error
- func RequestID(err error) (string, bool)
- func RetryAfter(err error) (time.Duration, bool)
- func RetryCount(err error) int
- func Timeout(err error) error
- func Timeoutf(format string, args ...any) error
- func Unauthorized(err error) error
- func Unauthorizedf(format string, args ...any) error
- func Validation(err error) error
- func Validationf(format string, args ...any) error
- func WithRequestID(err error, id string) error
- func WithRetryAfter(err error, d time.Duration) error
- func WithRetryCount(err error, count int) error
- type HTTPStatusCoder
- type ProviderCategory
- type RequestIDCoder
- type RetryAfterCoder
- type RetryCountCoder
Constants ¶
This section is empty.
Variables ¶
Re-export standard library functions so callers only need one import.
Functions ¶
func BudgetExceeded ¶
BudgetExceeded marks err as a budget / quota refusal — typically raised by a host (e.g. a sandbox host wrapping engine.UsageReporter) when a per-pod, per-tenant, or per-call token / cost / count limit has been hit. Use this instead of RateLimit for *internal* policy limits; RateLimit is for upstream / network rate-limit responses.
func BudgetExceededf ¶
func ClassifyHTTPStatus ¶
ClassifyHTTPStatus wraps a raw HTTP status code into an errdefs- classified error. Use this from callers that drive HTTP themselves (e.g. ollama, custom REST adapters). body is included verbatim in the error message to preserve provider diagnostics; pass an empty string when no body is available. Codes below 400 always map to Internal — the helper assumes callers have already gated on a non-2xx response.
The status mapping is ClassifyStatus's, plus the caller-supplied provider and body in the message: 402 and 403 stay permanent authorization/billing refusals rather than collapsing into a retryable auth failure.
func ClassifyProviderError ¶
ClassifyProviderError wraps an arbitrary provider error in an errdefs classification so pod-level policies (retry, circuit breaking, fail-fast on auth) can decide on it via the standard IsXxx checks. The original error chain is preserved; callers needing finer-grained signals (vendor-specific fields, llm.ErrorCategory) can still errors.As against the inner type.
Mapping:
HTTP 401, 403 → Unauthorized HTTP 402 → Forbidden (long-term unusable, not 429) HTTP 429 / "rate limit" / ... → RateLimit HTTP 400, 404, 405, 422 → Validation (client error, no retry) "context length exceeded" / ...→ Validation (input too large; client must shrink) HTTP 5xx / network flake → NotAvailable (transient, safe to retry)
Returns nil when err is nil; returns err untouched when it already carries an errdefs classification.
func ClassifyStatus ¶ added in v0.4.0
ClassifyStatus wraps cause with the errdefs classification one HTTP status implies, preserving the cause chain. Use it from a transport that already holds a provider-typed error and only needs the status mapped; callers that have a raw response body should use ClassifyHTTPStatus, which builds the message as well.
The mapping is the one every provider transport needs and the same one ClassifyHTTPStatus applies: 400/404/405/422 are validation, 401 unauthorized, 402/403 forbidden (billing and authorization refusals are permanent, not retryable), 409 conflict, 429 rate limit, 408/504 timeout, and everything else — including 5xx — not-available, which the router retries.
func Forbiddenf ¶
func FromContext ¶
FromContext maps a context error to the matching errdefs classification. It is the standard way for callers to surface a context.Done() failure so that pod / observability layers can distinguish a real timeout from a cooperative cancel:
- context.DeadlineExceeded → Timeout (HTTP 504; pod marks SLO miss).
- context.Canceled → Aborted (HTTP 409; pod treats as user stop, not a failure).
FromContext returns the input error unchanged when it is nil, when it already satisfies one of the errdefs marker interfaces (so callers can fold ctx.Err() into ClassifyProviderError pipelines without losing the original classification), or when it is some other error value (defensive — context.Cause() can surface arbitrary cancellation causes).
func HTTPStatus ¶
HTTPStatus returns the HTTP status code for an error based on its category. Unknown/uncategorized errors map to 500 Internal Server Error.
func HasClassification ¶
HasClassification reports whether err already carries any errdefs behavioural marker. Used by FromContext and by ClassifyProviderError / ClassifyHTTPStatus (in http.go) to avoid double-wrapping a pre-classified error and changing its observable category. Returns false for nil.
func Interrupted ¶
func Interruptedf ¶
func IsBudgetExceeded ¶
IsBudgetExceeded reports whether err carries the BudgetExceeded classification — i.e. a per-pod / per-tenant token, cost, or quota limit has been hit. Use this to distinguish "we are stopping you on purpose" from external rate limits (IsRateLimit) and from generic internal failures (IsInternal). Maps to HTTP 429 by default.
func IsConflict ¶
func IsForbidden ¶
func IsInternal ¶
func IsInterrupted ¶
func IsNotAvailable ¶
func IsNotFound ¶
func IsPolicyDenied ¶
IsPolicyDenied reports whether err was produced by a policy-layer refusal — tool allow-list, network egress filter, role-based access check, etc. Distinguishes "you are not allowed to do this in this pod" from authentication failures (IsUnauthorized) and from external authorisation failures (IsForbidden). Maps to HTTP 403 by default.
func IsRateLimit ¶
func IsUnauthorized ¶
func IsValidation ¶
func NotAvailable ¶
func NotAvailablef ¶
func ParseRetryAfter ¶
ParseRetryAfter parses the seconds form of a Retry-After header value. Invalid, empty, and negative values return zero.
func ParseRetryCount ¶
ParseRetryCount parses a zero-based retry-count header (e.g. the X-Stainless-Retry-Count header vendor SDKs send). Invalid, empty, and negative values return zero.
func PolicyDenied ¶
PolicyDenied marks err as a policy-layer refusal — tool allow-list rejection, network egress filter, role-based access check, etc. Use this instead of Forbidden for *internal* sandbox policy decisions; Forbidden is for upstream / authorisation responses.
func PolicyDeniedf ¶
func RateLimitf ¶
func RequestID ¶
RequestID reads the provider request identifier from an error chain. It reports false when the chain carries no identifier.
func RetryAfter ¶
RetryAfter reads the hint from an error chain. It reports false when the chain carries no hint or the hint is not positive.
func RetryCount ¶
RetryCount reads the wire-attempt count from an error chain. Zero means no count was recorded.
func Unauthorized ¶
func Unauthorizedf ¶
func Validation ¶
func Validationf ¶
func WithRequestID ¶
WithRequestID wraps err with a provider-assigned request identifier. Nil and empty identifiers return err unchanged so callers can attach them unconditionally.
func WithRetryAfter ¶
WithRetryAfter wraps err with a Retry-After hint. Nil and non-positive durations return err unchanged so callers can attach hints unconditionally.
func WithRetryCount ¶
WithRetryCount wraps err with the number of wire attempts already made. Nil and non-positive counts return err unchanged.
Types ¶
type HTTPStatusCoder ¶
type HTTPStatusCoder interface {
HTTPStatusCode() int
}
HTTPStatusCoder is implemented by errors that carry an HTTP status code. Provider SDKs (openai-go, anthropic-sdk-go, ...) typically expose their error types this way; ClassifyProviderError checks this interface first because a structured status is the most reliable signal.
type ProviderCategory ¶
type ProviderCategory int
ProviderCategory is a finer-grained classification dimension for errors coming back from external providers. It carries strictly more information than the errdefs IsXxx behavior set: 401/403 (Auth) and 402 (Billing) both map to Forbidden/Unauthorized for wire purposes, but consumers like core/inference.FallbackLLM need to distinguish them when choosing a cooldown duration. ContextOverflow and Permanent likewise both surface as Validation but warrant different telemetry buckets.
ProviderCategory is exported so sibling capabilities (core/inference chat fallback, future core/inference embedding rerank chains, ...) share one keyword table and one HTTP-code switch. New consumers SHOULD wrap it in a domain-specific type alias rather than referencing it directly, so the enum name reads naturally at the call site.
const ( ProviderTransient ProviderCategory = iota // network flake, 5xx ProviderRateLimit // 429 ProviderAuth // 401 / 403 ProviderBilling // 402 ProviderContextOverflow // input too large ProviderPermanent // 400 / 404 / 405 / 422 )
func ClassifyProvider ¶
func ClassifyProvider(err error) ProviderCategory
ClassifyProvider determines a ProviderCategory for an arbitrary error coming back from a provider SDK. Use this when you need the richer category dimension (e.g. choosing per-category cooldown); most call sites should prefer ClassifyProviderError, which folds the classification straight into an errdefs marker.
Match order is significant:
- structured HTTPStatusCoder — most reliable, set by SDK error types like openai-go's APIError;
- keyword scan — catches "context length exceeded" before its sibling "http 400" would match as Permanent;
- embedded HTTP code regex — catches providers that only expose the status as part of an error string ("api error: status 429: ...").
func ProviderCategoryFromHTTPCode ¶
func ProviderCategoryFromHTTPCode(code int) (ProviderCategory, bool)
ProviderCategoryFromHTTPCode maps a non-2xx HTTP status into a ProviderCategory. Returns (ProviderTransient, false) for codes that have no specific mapping (informational / 3xx / generic 5xx); callers SHOULD treat those as transient and retryable.
type RequestIDCoder ¶
type RequestIDCoder interface {
RequestID() string
}
RequestIDCoder is implemented by errors that carry a provider-assigned request identifier, useful for correlating a failure with the provider's own trace/log surface.
type RetryAfterCoder ¶
RetryAfterCoder is implemented by errors that carry a server-provided retry hint (typically from a Retry-After response header).
type RetryCountCoder ¶
type RetryCountCoder interface {
RetryCount() int
}
RetryCountCoder is implemented by errors that carry the number of wire attempts (HTTP sends) that already happened before the failure surfaced.