wavetermdev/waveterm · error

ai:model is required

Error message

ai:model is required

What it means

buildOpenAIHTTPRequest in openai-convertmessage.go validates chat options before building the request. 'ai:model is required' is thrown when opts.Model is empty, except that on a premium-rate-limit continuation the library substitutes DefaultOpenAIModel first. A model name is mandatory to construct the OpenAI request body, so the library fails fast.

Source

Thrown at pkg/aiusechat/openai/openai-convertmessage.go:203

	log.Printf("inputs (%d):", len(req.Input))
	for idx, input := range req.Input {
		debugPrintInput(idx, input)
	}
}

// buildOpenAIHTTPRequest creates a complete HTTP request for the OpenAI API
func buildOpenAIHTTPRequest(ctx context.Context, inputs []any, chatOpts uctypes.WaveChatOpts, cont *uctypes.WaveContinueResponse) (*http.Request, error) {
	opts := chatOpts.Config

	// If continuing from premium rate limit, downgrade to default model and medium thinking
	// (medium is more widely supported than low across different models)
	if cont != nil && cont.ContinueFromKind == uctypes.StopKindPremiumRateLimit {
		opts.Model = uctypes.DefaultOpenAIModel
		opts.ThinkingLevel = uctypes.ThinkingLevelMedium
	}

	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 = OpenAIDefaultMaxTokens
	}

	// injected data
	if chatOpts.TabState != "" {

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set ai:model in the configuration to a valid OpenAI model (e.g. gpt-4o or gpt-4.1)
  2. If building WaveChatOpts in code, assign Config.Model before calling RunOpenAIChatStep
  3. Verify the model is under the OpenAI provider's config section, not another backend's
  4. Optionally default to uctypes.DefaultOpenAIModel at the call site when Model is empty

Example fix

// before
opts := uctypes.WaveChatOpts{Config: uctypes.WaveChatOptsConfig{APIToken: key}}
// after
model := "gpt-4o"
if chatOpts.Config.Model == "" {
    chatOpts.Config.Model = uctypes.DefaultOpenAIModel
}
_ = model
Defensive patterns

Strategy: validation

Validate before calling

if chatOpts.Config.Model == "" {
    chatOpts.Config.Model = uctypes.DefaultOpenAIModel
}

Try / catch

if _, _, _, err := RunOpenAIChatStep(ctx, handler, chatOpts, cont); err != nil {
    if err.Error() == "ai:model is required" {
        chatOpts.Config.Model = uctypes.DefaultOpenAIModel
        return retry()
    }
    return err
}

Prevention

When it happens

Trigger: RunOpenAIChatStep is called where chatOpts.Config.Model == "" and the continuation is not StopKindPremiumRateLimit (that path force-sets DefaultOpenAIModel). Typical when the model setting is empty, cleared, or bound to the wrong provider config.

Common situations: Fresh install with API key but no model chosen; switching backends where the new provider has no default model mapped; config key typo or migration dropping the model; programmatic construction of WaveChatOpts omitting Model.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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