{"record":{"id":"5f3d92f4bc66a73d","repo":"siyuan-note/siyuan","slug":"provider-not-found","errorCode":null,"errorMessage":"provider not found","messagePattern":"provider not found","errorType":"validation","errorClass":null,"httpStatus":200,"severity":"error","filePath":"kernel/api/ai.go","lineNumber":68,"sourceCode":"\t\t}\n\t\tif strings.TrimSpace(provider.BaseURL) == \"\" {\n\t\t\treturn nil, errors.New(\"provider base URL is required\")\n\t\t}\n\t\tai := &conf.AI{Providers: []*conf.Provider{provider}}\n\t\tai.Normalize()\n\t\tif len(ai.Providers) != 1 {\n\t\t\treturn nil, errors.New(\"invalid provider config\")\n\t\t}\n\t\treturn ai.Providers[0], nil\n\t}\n\n\tproviderID, _ := arg[\"provider\"].(string)\n\tfor _, provider := range model.Conf.AI.Providers {\n\t\tif provider != nil && provider.ID == providerID {\n\t\t\treturn provider, nil\n\t\t}\n\t}\n\treturn nil, errors.New(\"provider not found\")\n}\n\nfunc chatGPT(c *gin.Context) {\n\tret := gulu.Ret.NewResult()\n\tdefer c.JSON(http.StatusOK, ret)\n\n\targ, ok := util.JsonArg(c, ret)\n\tif !ok {\n\t\treturn\n\t}\n\n\tvar msg string\n\tif !util.ParseJsonArgs(arg, ret, util.BindJsonArg(\"msg\", &msg, true, true)) {\n\t\treturn\n\t}\n\tret.Data = model.ChatGPT(msg)\n}\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/api/ai.go#L50-L86","documentation":"Returned by resolveAIProvider in kernel/api/ai.go, which backs POST /api/ai/chatGPT and /api/ai/chatGPTWithAction. When the request body has no inline providerConfig object, the kernel reads arg[\"provider\"] as a string ID and scans the configured providers in model.Conf.AI.Providers. If no configured provider has exactly that ID, the API envelope returns code -1 with this message.","triggerScenarios":"POST /api/ai/chatGPT with a \"provider\" field that is empty, misspelled, or refers to a provider deleted from Settings - AI; sending neither \"providerConfig\" nor a valid \"provider\"; sending a provider id that belongs to a different workspace or profile than the running kernel.","commonSituations":"The AI provider list was reset or reconfigured and a plugin still sends the old provider id; fresh install where no AI provider is configured yet; multiple providers configured but the request omits the provider field entirely; copying a request body between test and production workspaces with different provider ids.","solutions":["Pass the exact provider id from the current workspace's AI configuration (Settings - AI, or read the configured provider list) in the provider field","Omit provider and pass a full inline providerConfig object with baseURL, model and API key, which the kernel validates and normalizes itself","If no provider is configured at all, add one in Settings - AI before calling the chat endpoints","Confirm you are attached to the same workspace where the provider was configured (model.Conf.AI.Providers is per-workspace)"],"exampleFix":"// before\nfetchPost('/api/ai/chatGPT', { input: msg, provider: 'gpt' }); // stale/hand-written id -> \"provider not found\"\n\n// after\nconst providers = await fetchGet('/api/ai/getConfigs'); // read configured ids\nconst id = providers.ai.providers[0]?.id;\nif (!id) { /* configure a provider first */ }\nfetchPost('/api/ai/chatGPT', { input: msg, provider: id });","handlingStrategy":"validation","validationCode":"const cfg = await fetchGet('/api/ai/getConfigs');\nconst ids = new Set((cfg.data.ai.providers || []).map(p => p.id));\nif (!ids.has(providerId)) {\n  throw new Error(`provider [${providerId}] not configured`);\n}\nawait fetchPost('/api/ai/chatGPT', { input, provider: providerId });","typeGuard":"function isConfiguredProviderId(id: string, providers: { id: string }[]): boolean {\n  return providers.some(p => typeof p?.id === 'string' && p.id === id);\n}","tryCatchPattern":"// after fetchPost, inspect the envelope\nif (res.code === -1 && res.msg === 'provider not found') {\n  const fresh = await fetchGet('/api/ai/getConfigs'); // re-sync provider ids and retry once with a valid id\n}","preventionTips":["Fetch the provider list from the same workspace right before the call instead of hard-coding ids","Treat provider ids as per-workspace state; refresh them after settings changes or workspace switches","Prefer inline providerConfig for programmatic one-off calls — it bypasses id lookup entirely"],"tags":["ai","provider","config","api","siyuan"],"backgroundTag":"provider-id-not-found","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}