{"record":{"id":"b14bcb8431bb9dde","repo":"wavetermdev/waveterm","slug":"ai-model-is-required-b14bcb","errorCode":null,"errorMessage":"ai:model is required","messagePattern":"ai:model is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/openai/openai-convertmessage.go","lineNumber":203,"sourceCode":"\tlog.Printf(\"inputs (%d):\", len(req.Input))\n\tfor idx, input := range req.Input {\n\t\tdebugPrintInput(idx, input)\n\t}\n}\n\n// buildOpenAIHTTPRequest creates a complete HTTP request for the OpenAI API\nfunc buildOpenAIHTTPRequest(ctx context.Context, inputs []any, chatOpts uctypes.WaveChatOpts, cont *uctypes.WaveContinueResponse) (*http.Request, error) {\n\topts := chatOpts.Config\n\n\t// If continuing from premium rate limit, downgrade to default model and medium thinking\n\t// (medium is more widely supported than low across different models)\n\tif cont != nil && cont.ContinueFromKind == uctypes.StopKindPremiumRateLimit {\n\t\topts.Model = uctypes.DefaultOpenAIModel\n\t\topts.ThinkingLevel = uctypes.ThinkingLevelMedium\n\t}\n\n\tif opts.Model == \"\" {\n\t\treturn nil, errors.New(\"ai:model is required\")\n\t}\n\tif chatOpts.ClientId == \"\" {\n\t\treturn nil, errors.New(\"chatOpts.ClientId is required\")\n\t}\n\n\t// Set defaults\n\tendpoint := opts.Endpoint\n\tif endpoint == \"\" {\n\t\treturn nil, errors.New(\"ai:endpoint is required\")\n\t}\n\n\tmaxTokens := opts.MaxTokens\n\tif maxTokens <= 0 {\n\t\tmaxTokens = OpenAIDefaultMaxTokens\n\t}\n\n\t// injected data\n\tif chatOpts.TabState != \"\" {","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/openai/openai-convertmessage.go#L185-L221","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nopts := uctypes.WaveChatOpts{Config: uctypes.WaveChatOptsConfig{APIToken: key}}\n// after\nmodel := \"gpt-4o\"\nif chatOpts.Config.Model == \"\" {\n    chatOpts.Config.Model = uctypes.DefaultOpenAIModel\n}\n_ = model","handlingStrategy":"validation","validationCode":"if chatOpts.Config.Model == \"\" {\n    chatOpts.Config.Model = uctypes.DefaultOpenAIModel\n}","typeGuard":null,"tryCatchPattern":"if _, _, _, err := RunOpenAIChatStep(ctx, handler, chatOpts, cont); err != nil {\n    if err.Error() == \"ai:model is required\" {\n        chatOpts.Config.Model = uctypes.DefaultOpenAIModel\n        return retry()\n    }\n    return err\n}","preventionTips":["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"],"tags":["openai","configuration","missing-model"],"backgroundTag":"missing-config-value","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}