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
- Set ai:model in the configuration to a valid OpenAI model (e.g. gpt-4o or gpt-4.1)
- If building WaveChatOpts in code, assign Config.Model before calling RunOpenAIChatStep
- Verify the model is under the OpenAI provider's config section, not another backend's
- 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
- Pick a model when entering an OpenAI API key; keep the two settings together
- Default to uctypes.DefaultOpenAIModel when Model is unset in programmatic use
- Validate provider config (model, token, endpoint, ClientId) before starting any chat step
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:model is required
- ai:endpoint is required
- API type mismatch: chat has %s, chatOpts has %s
- model mismatch: chat has %s, chatOpts has %s
- No tab view found for the given webContents id
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/b14bcb8431bb9dde.
Report an issue: GitHub.