Skip to main content

Common Errors

This guide covers the most common errors you'll encounter when using the Go AI SDK and how to fix them.

API Key Issues​

Error: "Invalid API Key"​

Symptoms:

Error: provider error (401): Invalid API key provided
Error: authentication failed

Cause: The API key is missing, incorrect, or not properly loaded from environment variables.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"

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

func main() {
// Check if API key is set
apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
log.Fatal("OPENAI_API_KEY environment variable not set")
}

// Verify key is not empty or whitespace
if len(apiKey) < 20 {
log.Fatal("OPENAI_API_KEY appears to be invalid (too short)")
}

provider := openai.New(openai.Config{
APIKey: apiKey,
})

model, err := provider.LanguageModel("gpt-4")
if err != nil {
log.Fatalf("Failed to create model: %v", err)
}

ctx := context.Background()
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Hello!",
})
if err != nil {
log.Fatalf("Failed to generate text: %v", err)
}

fmt.Println(result.Text)
}

Best Practices:

  • Use environment variables for API keys (never hardcode)
  • Use .env files with godotenv for local development
  • Validate API keys on application startup
  • Use separate keys for development and production

Error: "Model Not Found"​

Symptoms:

Error: model "gpt-5" not found
Error: invalid model specified

Cause: Trying to use a model that doesn't exist or isn't available in your account.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"

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

func main() {
ctx := context.Background()
provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})

// Use valid model names
validModels := []string{
"gpt-4",
"gpt-4-turbo",
"gpt-4o",
"gpt-4o-mini",
"gpt-3.5-turbo",
}
log.Printf("known-good model names: %v", validModels)

// Try to create model with error handling
model, err := provider.LanguageModel("gpt-4")
if err != nil {
log.Printf("Failed to create gpt-4 model: %v", err)
log.Println("Falling back to gpt-4o-mini...")

model, err = provider.LanguageModel("gpt-4o-mini")
if err != nil {
log.Fatalf("Failed to create fallback model: %v", err)
}
}

result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Hello!",
})
if err != nil {
log.Fatalf("Failed to generate text: %v", err)
}

fmt.Println(result.Text)
}

Nil Pointer Errors​

Error: "nil pointer dereference"​

Symptoms:

panic: runtime error: invalid memory address or nil pointer dereference

Cause: Not checking for errors before using returned values, or accessing fields on nil structs.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"

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

func main() {
ctx := context.Background()

provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})

// ALWAYS check errors before using the returned value
model, err := provider.LanguageModel("gpt-4")
if err != nil {
log.Fatalf("Failed to create model: %v", err)
}
// Now it's safe to use model

// Check result is not nil before accessing fields
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Hello!",
})
if err != nil {
log.Fatalf("Failed to generate text: %v", err)
}

// Safe to access result.Text now
if result != nil {
fmt.Println(result.Text)
}
}

Channel and Streaming Errors​

Error: "Channel Already Closed"​

Symptoms:

panic: send on closed channel
panic: close of closed channel

Cause: Trying to read from a stream channel multiple times or not properly handling channel closure.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"

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

func main() {
ctx := context.Background()

provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
model, _ := provider.LanguageModel("gpt-4")

stream, err := ai.StreamText(ctx, ai.StreamTextOptions{
Model: model,
Prompt: "Write a short story",
})
if err != nil {
log.Fatal(err)
}

// Read from channel until it closes
// The range loop automatically handles channel closure
for chunk := range stream.Chunks() {
fmt.Print(chunk.Text)
}
// Channel is now closed - DO NOT try to read again

// Check for errors after stream completes
if err := stream.Err(); err != nil {
log.Printf("Stream error: %v", err)
}

// DO NOT try to read from Chunks again - it's closed
}

Error: "Goroutine Leak / Stream Not Consumed"​

Symptoms:

  • Application hangs indefinitely
  • Memory usage grows over time
  • Goroutines never terminate

Cause: Not consuming all values from a stream channel, causing the goroutine to block.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"
"time"

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

func processStream(ctx context.Context, model provider.LanguageModel, prompt string) error {
stream, err := ai.StreamText(ctx, ai.StreamTextOptions{
Model: model,
Prompt: prompt,
})
if err != nil {
return err
}

// ALWAYS consume the entire stream, even if you don't need all the data
for chunk := range stream.Chunks() {
fmt.Print(chunk.Text)

// If you need to exit early, the context will cancel the stream
select {
case <-ctx.Done():
// Stream will be automatically cleaned up
return ctx.Err()
default:
// Continue processing
}
}

return stream.Err()
}

func main() {
// Use context with timeout to prevent infinite hangs
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
model, _ := provider.LanguageModel("gpt-4")

if err := processStream(ctx, model, "Write a story"); err != nil {
log.Printf("Error: %v", err)
}
}

Import Errors​

Error: "Package Not Found"​

Symptoms:

cannot find package "github.com/digitallysavvy/go-ai/pkg/ai"

Cause: Module not downloaded or go.mod not properly initialized.

Solution:

# Initialize module (if not already done)
go mod init your-project-name

# Install the Go AI SDK
go get github.com/digitallysavvy/go-ai

# Tidy up dependencies
go mod tidy

# Verify installation
go list -m github.com/digitallysavvy/go-ai

Error: "Ambiguous Import"​

Symptoms:

ambiguous import: found package in multiple locations

Cause: Conflicting package names or vendored dependencies.

Solution:

package main

import (
"context"

// Use full import paths with aliases if needed
goai "github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"

// If you have naming conflicts, use aliases
aitools "github.com/digitallysavvy/go-ai/pkg/provider/types"
)

func main() {
ctx := context.Background()
_ = aitools.RoleUser // use the aliased import, same as any other import

model, _ := openai.New(openai.Config{}).LanguageModel("gpt-4o")

// Use aliases in your code
result, err := goai.GenerateText(ctx, goai.GenerateTextOptions{
Model: model,
Prompt: "Hello!",
})
_ = result
_ = err
}

Type Errors​

Error: "Type Mismatch"​

Symptoms:

cannot use X (type string) as type interface in argument
cannot convert X to type Y

Cause: Passing wrong types to SDK functions.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"

"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() {
ctx := context.Background()
provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
model, _ := provider.LanguageModel("gpt-4")

// CORRECT: Pass messages as proper types.Message slice, with Content
// as a []types.ContentPart, not a bare string
messages := []types.Message{
{
Role: types.RoleUser,
Content: []types.ContentPart{types.TextContent{Text: "Hello!"}},
},
}

result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Messages: messages, // Not strings
})
if err != nil {
log.Fatal(err)
}

fmt.Println(result.Text)
}

JSON Schema Errors​

Error: "Schema Validation Failed"​

Symptoms:

Error: schema validation failed: invalid type for field X
Error: generated object does not match schema

Cause: JSON schema doesn't match your Go struct, or schema is invalid.

Solution:

package main

import (
"context"
"encoding/json"
"fmt"
"log"
"os"

"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/openai"
goschema "github.com/digitallysavvy/go-ai/pkg/schema"
"github.com/invopop/jsonschema"
)

// Define struct with proper JSON tags
type Recipe struct {
Name string `json:"name" jsonschema:"required,description=Name of the recipe"`
Ingredients []string `json:"ingredients" jsonschema:"required,minItems=1,description=List of ingredients"`
Steps []string `json:"steps" jsonschema:"required,minItems=1,description=Cooking steps"`
PrepTime int `json:"prepTime" jsonschema:"minimum=0,description=Preparation time in minutes"`
}

func main() {
ctx := context.Background()
provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
model, _ := provider.LanguageModel("gpt-4")

// Generate a JSON schema from the struct with invopop/jsonschema, then
// wrap the resulting map in goschema.Schema — ai.GenerateObjectOptions.Schema
// takes a schema.Schema, not a *jsonschema.Schema directly.
reflector := jsonschema.Reflector{
AllowAdditionalProperties: false,
DoNotReference: true,
}
reflected := reflector.Reflect(&Recipe{})

schemaBytes, err := json.Marshal(reflected)
if err != nil {
log.Fatalf("Invalid schema: %v", err)
}
log.Printf("Using schema:\n%s", schemaBytes)

var schemaMap map[string]interface{}
if err := json.Unmarshal(schemaBytes, &schemaMap); err != nil {
log.Fatalf("Failed to decode schema: %v", err)
}

var recipe Recipe
if err := ai.GenerateObjectInto(ctx, ai.GenerateObjectOptions{
Model: model,
Schema: goschema.NewSimpleJSONSchema(schemaMap),
Prompt: "Generate a lasagna recipe",
}, &recipe); err != nil {
log.Fatalf("Failed to generate object: %v", err)
}

fmt.Printf("Recipe: %s\n", recipe.Name)
}

Context Errors​

Error: "Context Deadline Exceeded"​

Symptoms:

Error: context deadline exceeded
Request timed out

Cause: Operation took longer than the context timeout allows.

Solution:

package main

import (
"context"
"fmt"
"log"
"os"
"time"

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

func main() {
provider := openai.New(openai.Config{
APIKey: os.Getenv("OPENAI_API_KEY"),
})
model, _ := provider.LanguageModel("gpt-4")

// Increase timeout for long operations
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()

result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Write a detailed 5000-word essay on quantum computing",
})
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
log.Println("Operation timed out - increase the timeout or use streaming")

// Alternative: Use streaming for long responses
stream, err := ai.StreamText(context.Background(), ai.StreamTextOptions{
Model: model,
Prompt: "Write a detailed 5000-word essay on quantum computing",
})
if err != nil {
log.Fatal(err)
}

for chunk := range stream.Chunks() {
fmt.Print(chunk.Text)
}

if err := stream.Err(); err != nil {
log.Fatal(err)
}
return
}
log.Fatalf("Error: %v", err)
}

fmt.Println(result.Text)
}

Best Practices​

1. Always Check Errors​

// Bad
result, _ := ai.GenerateText(ctx, options)

// Good
result, err := ai.GenerateText(ctx, options)
if err != nil {
return fmt.Errorf("generation failed: %w", err)
}

2. Use Context Timeouts​

// Always use context with timeout for production
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

3. Consume Streams Completely​

// Always read all values from stream channels
for chunk := range stream.Chunks() {
// Process chunk
}
// Check error after stream closes
if err := stream.Err(); err != nil {
log.Printf("Stream error: %v", err)
}

4. Validate Configuration​

// Check configuration at startup
if apiKey := os.Getenv("OPENAI_API_KEY"); apiKey == "" {
log.Fatal("Missing OPENAI_API_KEY")
}

5. Use Proper Types​

// Use SDK types, not raw strings
messages := []types.Message{
{Role: types.RoleUser, Content: "Hello"},
}

See Also​