Skip to main content

Error Types

Error types returned by Go AI SDK functions.

Typed Errors​

Many SDK functions return specific error types instead of (or in addition to) plain errors.New/fmt.Errorf values. Use errors.As to detect them. Most live in pkg/ai; a few tool/provider-level ones live in pkg/provider/types and pkg/provider.

TypePackageKey FieldsWhen it's returned
NoSuchToolErroraiToolName, AvailableToolsModel called a tool that isn't available
InvalidToolInputErroraiToolName, ToolInput, CauseTool input doesn't satisfy the tool's schema
ToolCallRepairErroraiCause, OriginalErrorRepairToolCall failed to fix a bad tool call
ToolChoiceViolationErroraiToolChoice, FinishReason, Provider, ModelIDResponse didn't honor a required/specific ToolChoice
ToolCallNotFoundForApprovalErroraiToolCallID, ApprovalIDApproval references a tool call missing from history
InvalidToolApprovalErroraiApprovalIDApproval response has no matching request
InvalidToolApprovalSignatureErroraiApprovalID, ToolCallID, ReasonSigned approval could not be verified
NoObjectGeneratedErroraiMessage, Cause, Text, Response, Usage, FinishReasonGenerateObject/StreamObject produced no valid object
NoOutputGeneratedErroraiMessage, CauseStream ended before any output or finish chunk
NoImageGeneratedErroraiResponses, CallsGenerateImage produced zero images
NoSpeechGeneratedErroraiResponsesGenerateSpeech produced no audio
NoVideoGeneratedErroraiResponsesGenerateVideo produced no videos
NoTranscriptGeneratedErroraiResponsesTranscribe produced no text
NoTranslationGeneratedErroraiResponseSpeech translation produced no audio or text
MessageConversionErroraiOriginalMessage, Message, CauseA UI message couldn't convert to a model message
TimeoutErroraiReason, ErrA configured TimeoutConfig deadline was hit
UIMessageStreamErroraiChunkType, ChunkID, MessageA UI message stream received an out-of-sequence chunk
types.MissingToolResultErrorprovider/typesToolCallID, ToolName, MessageA provider-executed tool didn't return a result
types.MissingToolResultsErrorprovider/typesToolCallIDs, MessageMultiple provider-executed tools are missing results
types.ToolExecutionErrorprovider/typesToolCallID, ToolName, Err, ProviderExecutedA tool's Execute function returned an error
provider.BatchErrorproviderMessage, Type, Code, StatusCodeSerializable error info for a failed batch item
provider.NoSuchUploadAPIErrorproviderAPIProvider has no upload API of the requested kind

The SDK also exposes Is*Error(err) bool helper functions for most of the types above as an alternative to errors.As, for example ai.IsNoSuchToolError, ai.IsInvalidToolInputError, ai.IsToolChoiceViolationError, ai.IsNoImageGeneratedError, ai.IsNoOutputGeneratedError, and ai.IsMessageConversionError. NoObjectGeneratedError and TimeoutError have no Is* helper; use errors.As for those.

Example: errors.As​

package main

import (
"context"
"errors"
"fmt"
"log"

"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/provider/types"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"
)

func main() {
p := openai.New(openai.Config{APIKey: "your-api-key"})
model, _ := p.LanguageModel("gpt-4")

weatherTool := types.Tool{Name: "get_weather"}

result, err := ai.GenerateText(context.Background(), ai.GenerateTextOptions{
Model: model,
Prompt: "Use the weather tool",
Tools: []types.Tool{weatherTool},
StopWhen: []ai.StopCondition{ai.IsStepCount(5)},
})
if err != nil {
var noSuchTool *ai.NoSuchToolError
var invalidInput *ai.InvalidToolInputError
switch {
case errors.As(err, &noSuchTool):
log.Printf("model tried calling unknown tool %q", noSuchTool.ToolName)
case errors.As(err, &invalidInput):
log.Printf("tool %q got invalid input: %v", invalidInput.ToolName, invalidInput.Cause)
default:
log.Fatal(err)
}
return
}

fmt.Println(result.Text)
}

Untyped Errors​

Many lower-level validation and provider failures are still plain Go errors with descriptive messages rather than a dedicated type, for example:

"model is required"
"prompt is required"
provider-specific HTTP errors wrapped from the provider's API response

Check these with strings.Contains(err.Error(), "...") as shown below, or prefer the typed errors above and ai.Is*Error helpers where one exists.

Error Handling Patterns​

Basic Error Handling​

package main

import (
"context"
"log"

"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"
)

func main() {
p := openai.New(openai.Config{APIKey: "your-api-key"})
model, _ := p.LanguageModel("gpt-4")

opts := ai.GenerateTextOptions{Model: model, Prompt: "Hello"}

result, err := ai.GenerateText(context.Background(), opts)
if err != nil {
log.Fatal(err)
}
log.Println(result.Text)
}

Timeout Errors​

result, err := ai.GenerateText(ctx, opts)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
log.Println("Request timed out")
return
}
log.Fatal(err)
}

Cancellation Errors​

ctx, cancel := context.WithCancel(context.Background())

go func() {
time.Sleep(5 * time.Second)
cancel()
}()

result, err := ai.GenerateText(ctx, opts)
if err != nil {
if errors.Is(err, context.Canceled) {
log.Println("Request was canceled")
return
}
log.Fatal(err)
}

Validation Errors​

result, err := ai.GenerateText(ctx, opts)
if err != nil {
switch {
case strings.Contains(err.Error(), "model is required"):
log.Println("Must provide a model")
case strings.Contains(err.Error(), "prompt is required"):
log.Println("Must provide a prompt or messages")
default:
log.Println("Unknown validation error:", err)
}
return
}

Provider-Specific Errors​

result, err := ai.GenerateText(ctx, opts)
if err != nil {
switch {
case strings.Contains(err.Error(), "API key"):
log.Println("Invalid or missing API key")
case strings.Contains(err.Error(), "rate limit"):
log.Println("Rate limited - retry later")
time.Sleep(time.Minute)
// Retry logic
case strings.Contains(err.Error(), "content policy"):
log.Println("Content policy violation")
case strings.Contains(err.Error(), "invalid model"):
log.Println("Model not found or not supported")
default:
log.Println("Provider error:", err)
}
return
}

Retry Logic​

func generateWithRetry(ctx context.Context, opts ai.GenerateTextOptions, maxRetries int) (*ai.GenerateTextResult, error) {
var result *ai.GenerateTextResult
var err error

for attempt := 0; attempt < maxRetries; attempt++ {
result, err = ai.GenerateText(ctx, opts)
if err == nil {
return result, nil
}

// Check if error is retryable
if strings.Contains(err.Error(), "rate limit") {
waitTime := time.Duration(attempt+1) * time.Second
log.Printf("Rate limited, retrying in %v (attempt %d/%d)",
waitTime, attempt+1, maxRetries)
time.Sleep(waitTime)
continue
}

// Non-retryable error
return nil, err
}

return nil, fmt.Errorf("max retries exceeded: %w", err)
}

Tool Execution Errors​

weatherTool := types.Tool{
Name: "get_weather",
Description: "Get weather",
Parameters: weatherSchema,
Execute: func(ctx context.Context, input map[string]interface{}, opts types.ToolExecutionOptions) (interface{}, error) {
location, ok := input["location"].(string)
if !ok {
return nil, fmt.Errorf("location must be a string")
}

weather, err := fetchWeather(location)
if err != nil {
return nil, fmt.Errorf("failed to fetch weather: %w", err)
}

return weather, nil
},
}

result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "What's the weather?",
Tools: []types.Tool{weatherTool},
StopWhen: []ai.StopCondition{ai.IsStepCount(5)},
})
if err != nil {
if strings.Contains(err.Error(), "tool execution failed") {
log.Println("A tool failed during execution:", err)
}
}

Stream Errors​

result, err := ai.StreamText(ctx, opts)
if err != nil {
log.Fatal("Failed to start stream:", err)
}
defer result.Close()

for {
chunk, err := result.Stream().Next()
if err == io.EOF {
break
}
if err != nil {
log.Printf("Stream error: %v", err)
break
}

// Process chunk
}

// Check for accumulated errors
if result.Err() != nil {
log.Printf("Stream had errors: %v", result.Err())
}

Schema Validation Errors​

result, err := ai.GenerateObject(ctx, ai.GenerateObjectOptions{
Model: model,
Prompt: "Generate user data",
Schema: schema,
})
if err != nil {
if strings.Contains(err.Error(), "validation failed") {
log.Println("Generated object doesn't match schema:", err)
}
return
}

See Also​