{"record":{"id":"b090a3c3ff18d0b6","repo":"wavetermdev/waveterm","slug":"model-mismatch-chat-has-s-chatopts-has-s-b090a3","errorCode":null,"errorMessage":"model mismatch: chat has %s, chatOpts has %s","messagePattern":"model mismatch: chat has (.+?), chatOpts has (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/openai/openai-backend.go","lineNumber":484,"sourceCode":"\tchatOpts uctypes.WaveChatOpts,\n\tcont *uctypes.WaveContinueResponse,\n) (*uctypes.WaveStopReason, []*OpenAIChatMessage, *uctypes.RateLimitInfo, error) {\n\tif sse == nil {\n\t\treturn nil, nil, nil, errors.New(\"sse handler is nil\")\n\t}\n\n\t// Get chat from store\n\tchat := chatstore.DefaultChatStore.Get(chatOpts.ChatId)\n\tif chat == nil {\n\t\treturn nil, nil, nil, fmt.Errorf(\"chat not found: %s\", chatOpts.ChatId)\n\t}\n\n\t// Validate that chatOpts.Config match the chat's stored configuration\n\tif chat.APIType != chatOpts.Config.APIType {\n\t\treturn nil, nil, nil, fmt.Errorf(\"API type mismatch: chat has %s, chatOpts has %s\", chat.APIType, chatOpts.Config.APIType)\n\t}\n\tif !uctypes.AreModelsCompatible(chat.APIType, chat.Model, chatOpts.Config.Model) {\n\t\treturn nil, nil, nil, fmt.Errorf(\"model mismatch: chat has %s, chatOpts has %s\", chat.Model, chatOpts.Config.Model)\n\t}\n\tif chat.APIVersion != chatOpts.Config.APIVersion {\n\t\treturn nil, nil, nil, fmt.Errorf(\"API version mismatch: chat has %s, chatOpts has %s\", chat.APIVersion, chatOpts.Config.APIVersion)\n\t}\n\n\t// Context with timeout if provided.\n\tif chatOpts.Config.TimeoutMs > 0 {\n\t\tvar cancel context.CancelFunc\n\t\tctx, cancel = context.WithTimeout(ctx, time.Duration(chatOpts.Config.TimeoutMs)*time.Millisecond)\n\t\tdefer cancel()\n\t}\n\n\t// Validate continuation if provided\n\tif cont != nil {\n\t\tif !uctypes.AreModelsCompatible(chat.APIType, chatOpts.Config.Model, cont.Model) {\n\t\t\treturn nil, nil, nil, fmt.Errorf(\"cannot continue with a different model, model:%q, cont-model:%q\", chatOpts.Config.Model, cont.Model)\n\t\t}\n\t}","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/openai/openai-backend.go#L466-L502","documentation":"RunOpenAIChatStep checks model compatibility with uctypes.AreModelsCompatible(chat.APIType, chat.Model, chatOpts.Config.Model) and returns \"model mismatch\" at openai-backend.go:484 when the chat's stored model is incompatible with the model in the request options. This prevents mixing history generated by one model into a request for an incompatible model.","triggerScenarios":"Calling RunOpenAIChatStep with Config.Model different (and not compatible per AreModelsCompatible) from the model the chat was created with — e.g. user switches model mid-conversation, or opts built from defaults rather than the chat record.","commonSituations":"Model upgraded/renamed server-side so old chats carry a retired model name; user changes model selection in the UI while continuing a conversation; config file defaults overriding the chat's model.","solutions":["Set chatOpts.Config.Model from the chat's stored model (chat.Model) before stepping","Start a new chat when intentionally switching to a different model","Check uctypes.AreModelsCompatible to see whether the two models are considered compatible aliases (e.g. versioned variants) before assuming mismatch","If the model was deprecated, migrate the chat to the new compatible model name once, or recreate the chat"],"exampleFix":"// before\nchatOpts.Config.Model = \"gpt-4.1\" // switched mid-chat\nRunOpenAIChatStep(ctx, sse, chatOpts, nil)\n// after\nchat := chatstore.DefaultChatStore.Get(chatOpts.ChatId)\nchatOpts.Config.Model = chat.Model // continue with the chat's model\nRunOpenAIChatStep(ctx, sse, chatOpts, nil)","handlingStrategy":"validation","validationCode":"chat := chatstore.DefaultChatStore.Get(chatOpts.ChatId)\nif chat != nil && !uctypes.AreModelsCompatible(chat.APIType, chat.Model, chatOpts.Config.Model) {\n    chatOpts.Config.Model = chat.Model // or start a new chat with the new model\n}","typeGuard":"func modelCompatible(chatOpts uctypes.WaveChatOpts) bool {\n    chat := chatstore.DefaultChatStore.Get(chatOpts.ChatId)\n    return chat != nil && uctypes.AreModelsCompatible(chat.APIType, chat.Model, chatOpts.Config.Model)\n}","tryCatchPattern":"if _, _, _, err := RunOpenAIChatStep(ctx, sse, chatOpts, nil); err != nil {\n    if strings.HasPrefix(err.Error(), \"model mismatch\") {\n        // either reset Config.Model to the chat's model or create a new chat\n        return nil\n    }\n    return err\n}","preventionTips":["Read the model from the chat record for continuation steps","Check AreModelsCompatible before switching model strings (aliases count)","Start a fresh chat on intentional model change","Watch for deprecated model names after upstream upgrades"],"tags":["go","model","configuration","openai"],"backgroundTag":"model-mismatch","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}