Skip to content

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.

go
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 CodeMeaning
429Too Many Requests (rate limited)
503Service 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).

go
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.

go
func IsOverflow(message string) bool

Returns 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.

go
func ParseHTTPError(providerID string, statusCode int, body []byte) error

Parameters:

NameTypeDescription
providerIDstringProvider identifier (e.g., "openai"). Affects retry behavior.
statusCodeintHTTP status code from the response.
body[]byteRaw 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).

go
func ParseStreamError(body []byte) *ParsedStreamError

Returns nil if the body does not contain a recognized error event. When non-nil, the ParsedStreamError contains:

go
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:

CodeTypeRetryable
context_length_exceededcontext_overflowNo
insufficient_quotaapi_errorNo
usage_not_includedapi_errorNo
invalid_promptapi_errorNo

Usage Patterns

Checking for a specific error type

go
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

go
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

go
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())
    }
})

Released under the MIT License.