wavetermdev/waveterm · error

ai:model is required

Error message

ai:model is required

What it means

buildAnthropicHTTPRequest requires opts.Model (from chatOpts.Config) because every Anthropic Messages API request must name a model. When Config.Model is empty the request cannot be built, so it fails fast with 'ai:model is required' before any network traffic.

Source

Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:34

	"slices"
	"strings"

	"github.com/google/uuid"
	"github.com/wavetermdev/waveterm/pkg/aiusechat/chatstore"
	"github.com/wavetermdev/waveterm/pkg/aiusechat/uctypes"
	"github.com/wavetermdev/waveterm/pkg/util/logutil"
	"github.com/wavetermdev/waveterm/pkg/util/utilfn"
	"github.com/wavetermdev/waveterm/pkg/wavebase"
)

// these conversions are based off the anthropic spec
// and the aiprompts/aisdk-uimessage-type.md doc (v5)

// buildAnthropicHTTPRequest creates a complete HTTP request for the Anthropic API
func buildAnthropicHTTPRequest(ctx context.Context, msgs []anthropicInputMessage, chatOpts uctypes.WaveChatOpts) (*http.Request, error) {
	opts := chatOpts.Config
	if opts.Model == "" {
		return nil, errors.New("ai:model is required")
	}
	if chatOpts.ClientId == "" {
		return nil, errors.New("chatOpts.ClientId is required")
	}

	// Set defaults
	endpoint := opts.Endpoint
	if endpoint == "" {
		return nil, errors.New("ai:endpoint is required")
	}

	maxTokens := opts.MaxTokens
	if maxTokens <= 0 {
		maxTokens = AnthropicDefaultMaxTokens
	}

	// Convert messages to clear FileName fields from Source blocks
	convertedMsgs := make([]anthropicInputMessage, len(msgs))

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set chatOpts.Config.Model to a valid Anthropic model id (e.g. "claude-sonnet-4-20250514") before calling.
  2. If model comes from config, add/fix the 'ai:model' setting in the Wave term/block config and reload.
  3. Add pre-call validation that surfaces the empty Model at configuration time.

Example fix

// before
chatOpts := uctypes.WaveChatOpts{Config: uctypes.AIConfig{}}

// after
chatOpts := uctypes.WaveChatOpts{Config: uctypes.AIConfig{Model: "claude-sonnet-4-20250514"}}
Defensive patterns

Strategy: validation

Validate before calling

if chatOpts.Config.Model == "" {
    return fmt.Errorf("config error: ai:model must be set before calling anthropic chat")
}

Type guard

func hasModel(cfg uctypes.AIConfig) bool { return cfg.Model != "" }

Try / catch

_, _, _, err := RunAnthropicChatStep(ctx, sse, chatOpts, cont)
if err != nil && strings.Contains(err.Error(), "ai:model is required") {
    return fmt.Errorf("set 'ai:model' in your term/block config: %w", err)
}

Prevention

When it happens

Trigger: Calling RunAnthropicChatStep with chatOpts.Config.Model unset (empty string) — e.g. a WaveChatOpts built from partial config or a preset that never sets Model.

Common situations: Missing 'ai:model' key in user/term config; config loaded from an env or profile that predates the model field; constructing Config{} programmatically in tests; typo'd config key so the model value lands elsewhere.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/f64348692fdecf3d. Report an issue: GitHub.