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


PanicError ​

Indicates that a user callback or StopWhen predicate panicked during execution.

go
type PanicError struct {
    Phase string
    Value any
    Stack []byte
}

Use errors.As to inspect the phase. Value and Stack may contain sensitive data and are intentionally omitted from Error() output.


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")
  • xAI / Grok ("maximum prompt length is N")
  • Groq ("reduce the length of the messages")
  • OpenRouter / DeepSeek ("maximum context length is N tokens")
  • GitHub Copilot ("exceeds the limit of N")
  • llama.cpp / LM Studio ("exceeds the available context size", "greater than the context length")
  • MiniMax ("context window exceeds limit")
  • Kimi / Moonshot ("exceeded model token limit")
  • Cerebras / Mistral (400/413 status with no body)
  • Generic fallback (regex: (?i)context[_ ]length[_ ]exceeded)

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 three common API formats:

  • Chat Completions format: {"error": {"message": "..."}}
  • Responses API format: {"message": "...", "code": "...", "type": "..."} — goai extracts only the message field.
  • {"error": "<message>"}: the error field as a plain string.

ParseHTTPErrorWithHeaders ​

Like ParseHTTPError but preserves retry-related response headers (retry-after, retry-after-ms) on the returned *APIError. Used by providers to support header-based backoff.

go
func ParseHTTPErrorWithHeaders(providerID string, statusCode int, body []byte, headers http.Header) error

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 StreamErrorType string

const (
    StreamErrorContextOverflow StreamErrorType = "context_overflow"
    StreamErrorAPI             StreamErrorType = "api_error"
)

type ParsedStreamError struct {
    Type         StreamErrorType // "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:

CodeTypeRetryableMessage
context_length_exceededcontext_overflowNo"Input exceeds context window of this model"
insufficient_quotaapi_errorNo"Quota exceeded. Check your plan and billing details."
usage_not_includedapi_errorNo"To use Codex with your ChatGPT plan, upgrade to Plus."
invalid_promptapi_errorNo"Invalid prompt." (or the provider's message)

ClassifyStreamError ​

Higher-level variant of ParseStreamError that returns typed errors directly. Returns *ContextOverflowError or *APIError, or nil if the data is not a recognized error event.

go
func ClassifyStreamError(body []byte) error

ErrUnknownTool ​

Sentinel error set on ToolCallInfo.Error when a tool call references a tool not in the tool map during auto tool loop execution. Defined in generate.go.

go
var ErrUnknownTool = errors.New("goai: unknown tool")

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.