Errors
GoAI defines typed error values for API failures. Use errors.As to inspect error details and decide how to handle them.
Import: github.com/zendev-sh/goai
APIError
Represents a non-overflow API error from the provider.
type APIError struct {
Message string // Human-readable error message.
StatusCode int // HTTP status code.
IsRetryable bool // Whether this error can be retried.
ResponseBody string // Raw response body for debugging.
ResponseHeaders map[string]string // Selected response headers.
}APIError implements the error interface via its Error() method, which returns the Message field.
Retryable Status Codes
The following HTTP status codes produce retryable errors:
| Status Code | Meaning |
|---|---|
| 429 | Too Many Requests (rate limited) |
| 503 | Service Unavailable |
| 500+ | Any server error |
| 404 (OpenAI only) | Intermittent model availability |
GoAI's built-in retry logic (controlled by WithMaxRetries, default 2) automatically retries these errors with exponential backoff. Non-retryable errors are returned immediately.
ContextOverflowError
Indicates the prompt exceeded the model's context window. This error is never retryable - the request must be modified (e.g., by shortening the conversation history).
type ContextOverflowError struct {
Message string // Human-readable error message.
ResponseBody string // Raw response body.
}GoAI detects context overflow from error messages across all supported providers, including:
- Anthropic ("prompt is too long")
- Amazon Bedrock ("input is too long for requested model")
- OpenAI ("exceeds the context window")
- Google Gemini ("input token count exceeds the maximum")
- And many others (xAI, Groq, OpenRouter, DeepSeek, etc.)
IsOverflow
A helper function that checks if an error message indicates a context overflow. Useful when you have a raw error string and need to classify it.
func IsOverflow(message string) boolReturns true if the message matches any known overflow pattern.
ParseHTTPError
Classifies an HTTP error response into either *ContextOverflowError or *APIError. Called internally by provider implementations.
func ParseHTTPError(providerID string, statusCode int, body []byte) errorParameters:
| Name | Type | Description |
|---|---|---|
providerID | string | Provider identifier (e.g., "openai"). Affects retry behavior. |
statusCode | int | HTTP status code from the response. |
body | []byte | Raw response body. |
Returns: *ContextOverflowError if the error message matches an overflow pattern, otherwise *APIError.
The function extracts human-readable error messages from two common API formats:
- Chat Completions format:
{"error": {"message": "..."}} - Responses API format:
{"message": "...", "code": "...", "type": "..."}
ParseStreamError
Parses error events from SSE streams (used by Anthropic and OpenAI streaming).
func ParseStreamError(body []byte) *ParsedStreamErrorReturns nil if the body does not contain a recognized error event. When non-nil, the ParsedStreamError contains:
type ParsedStreamError struct {
Type string // "context_overflow" or "api_error".
Message string // Human-readable error message.
IsRetryable bool // Whether this error can be retried.
ResponseBody string // Raw event body.
}Recognized stream error codes:
| Code | Type | Retryable |
|---|---|---|
context_length_exceeded | context_overflow | No |
insufficient_quota | api_error | No |
usage_not_included | api_error | No |
invalid_prompt | api_error | No |
Usage Patterns
Checking for a specific error type
result, err := goai.GenerateText(ctx, model,
goai.WithPrompt("..."),
)
if err != nil {
var overflow *goai.ContextOverflowError
if errors.As(err, &overflow) {
// Prompt too long - truncate conversation and retry.
fmt.Println("Context overflow:", overflow.Message)
return
}
var apiErr *goai.APIError
if errors.As(err, &apiErr) {
fmt.Printf("API error %d: %s (retryable: %v)\n",
apiErr.StatusCode, apiErr.Message, apiErr.IsRetryable)
return
}
// Other errors (network, context cancelled, etc.)
log.Fatal(err)
}Handling overflow in a conversation loop
for {
result, err := goai.GenerateText(ctx, model,
goai.WithMessages(messages...),
)
var overflow *goai.ContextOverflowError
if errors.As(err, &overflow) {
// Remove oldest messages and retry.
messages = messages[2:]
continue
}
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Text)
break
}Accessing error details in telemetry hooks
goai.WithOnResponse(func(info goai.ResponseInfo) {
if info.Error != nil {
fmt.Printf("Request failed (status %d): %v\n", info.StatusCode, info.Error)
} else {
fmt.Printf("OK - %d tokens in %.2fs\n", info.Usage.TotalTokens, info.Latency.Seconds())
}
})