ClassifyModelError classifies an error for the retry/fallback decision. If the error chain contains a *StatusError (wrapped by provider adapters), its StatusCode and RetryAfter fields are used directly — no provider-specific imports needed in the caller. Returns: - retryable=true: retry the SAM
(err error)
| 579 | // deciding whether to retry (when no fallback is configured) or skip to the next |
| 580 | // model (when fallbacks are available). |
| 581 | func ClassifyModelError(err error) (retryable, rateLimited bool, retryAfter time.Duration) { |
| 582 | if err == nil { |
| 583 | return false, false, 0 |
| 584 | } |
| 585 | |
| 586 | // Context cancellation and deadline are never retryable. |
| 587 | if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { |
| 588 | return false, false, 0 |
| 589 | } |
| 590 | |
| 591 | // Context overflow errors are never retryable — retrying the same oversized |
| 592 | // payload will always fail. |
| 593 | if IsContextOverflowError(err) { |
| 594 | return false, false, 0 |
| 595 | } |
| 596 | |
| 597 | // Primary path: typed StatusError wrapped by provider adapters. |
| 598 | var statusErr *StatusError |
| 599 | if errors.As(err, &statusErr) { |
| 600 | if statusErr.StatusCode == http.StatusTooManyRequests { |
| 601 | return false, true, statusErr.RetryAfter |
| 602 | } |
| 603 | return isRetryableStatusCode(statusErr.StatusCode) || matchesTransientPattern(err), false, 0 |
| 604 | } |
| 605 | |
| 606 | // Fallback: providers that don't yet wrap (e.g. Bedrock), or non-provider |
| 607 | // errors (network, pattern matching). |
| 608 | statusCode := extractHTTPStatusCode(err) |
| 609 | if statusCode == http.StatusTooManyRequests { |
| 610 | return false, true, 0 // No Retry-After without StatusError |
| 611 | } |
| 612 | if statusCode != 0 { |
| 613 | return isRetryableStatusCode(statusCode) || matchesTransientPattern(err), false, 0 |
| 614 | } |
| 615 | return isRetryableModelError(err), false, 0 |
| 616 | } |
| 617 | |
| 618 | // FormatError returns a user-friendly error message for model errors. |
| 619 | // Overflow errors get a kind-specific actionable message; other errors fall |