{"record":{"id":"5051fd5d1568a288","repo":"siyuan-note/siyuan","slug":"no-ai-provider-configured","errorCode":null,"errorMessage":"no AI provider configured","messagePattern":"no AI provider configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/ai.go","lineNumber":91,"sourceCode":"func chatGPTWithAction(msg string, action string, cloud bool) (ret string) {\n\taction = strings.TrimSpace(action)\n\tif \"\" != action {\n\t\tmsg = action + \":\\n\\n\" + msg\n\t}\n\tret, _, err := chatGPTComplete(msg, nil, cloud)\n\tif err != nil {\n\t\treturn\n\t}\n\treturn\n}\n\nfunc chatGPTComplete(msg string, contextMsgs []string, cloud bool) (ret string, retContextMsgs []string, err error) {\n\tutil.PushEndlessProgress(\"Requesting...\")\n\tdefer util.ClearPushProgress(100)\n\n\tprov, m := Conf.AI.GetEditingModel()\n\tif nil == prov || nil == m {\n\t\terr = errors.New(\"no AI provider configured\")\n\t\treturn\n\t}\n\n\tediting := Conf.AI.Editing\n\tif nil == editing {\n\t\terr = errors.New(\"no AI editing config\")\n\t\treturn\n\t}\n\n\tif editing.MaxHistoryMessages < len(contextMsgs) {\n\t\tcontextMsgs = contextMsgs[len(contextMsgs)-editing.MaxHistoryMessages:]\n\t}\n\n\tvar gpt GPT\n\tif cloud {\n\t\tgpt = &CloudGPT{}\n\t} else {\n\t\tgpt = &OpenAIGPT{","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/model/ai.go#L73-L109","documentation":"Returned by chatGPTComplete when Conf.AI.GetEditingModel() returns a nil provider or a nil model. GetEditingModel first requires ai.Editing to be non-nil with a non-empty ModelID, then searches enabled providers for a model whose ID, DisplayName, or Name matches; if none is found (or no provider is enabled), both returns are nil and this error fires. It means the AI editing feature has no usable backend selected.","triggerScenarios":"Invoking any AI editing entry point (ChatGPT, ChatGPTWithAction, or a cloud AI path) while Conf.AI.GetEditingModel() yields nil — e.g. Editing.ModelID is empty, the referenced model was removed/renamed, or no provider is enabled.","commonSituations":"Fresh install with no AI provider configured; a user changed a model identifier in config but did not update Editing.ModelID; all providers disabled after an API-key removal; a config migration that reset provider/model enabled flags.","solutions":["Open Settings - AI and configure at least one provider with a valid API key and base URL, enable it, and select an editing model.","If you edited conf.json by hand, ensure ai.editing.modelId matches an enabled model's id under an enabled provider, and that provider.enabled and model.enabled are true.","Restart the kernel after changing AI config so Conf reloads, or use the settings API to apply the change.","Verify the model Name/ID is spelled exactly (GetEditingModel falls back to DisplayName then Name, but a typo still misses all three)."],"exampleFix":"// before: editing.ModelID references a removed model\nai.Editing = &Editing{ModelID: \"gpt-3.5-turbo\"}  // model no longer present\n// after\nai.Editing = &Editing{ModelID: \"gpt-4o-mini\"}  // matches an enabled model","handlingStrategy":"validation","validationCode":"prov, m := Conf.AI.GetEditingModel()\nif prov == nil || m == nil {\n    return errors.New(\"configure an AI provider and select an editing model first\")\n}","typeGuard":"func editingModelReady(ai *conf.AI) bool {\n    p, m := ai.GetEditingModel()\n    return p != nil && m != nil\n}","tryCatchPattern":null,"preventionTips":["Configure and enable a provider with a valid API key before invoking AI features.","Keep Editing.ModelID in sync with an enabled model's identifier.","Gate AI entry points on isOpenAIAPIEnabled()/HasAnyProvider() before calling."],"tags":["ai","config","openai","provider","chatgpt"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}