{"record":{"id":"8692d483f648c70d","repo":"gitbutlerapp/gitbutler","slug":"when-using-openai-in-a-bring-your-own-key-configur","errorCode":null,"errorMessage":"When using OpenAI in a bring your own key configuration, you must provide a valid token","messagePattern":"When using OpenAI in a bring your own key configuration, you must provide a valid token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/lib/ai/service.ts","lineNumber":343,"sourceCode":"\n\t\tif (modelKind === ModelKind.LMStudio) {\n\t\t\tconst lmStudioEndpoint = await this.getLMStudioEndpoint();\n\t\t\tconst lmStudioModelName = await this.getLMStudioModelName();\n\n\t\t\tif (!lmStudioEndpoint) {\n\t\t\t\tthrow new Error(\"When using LM Studio, you must provide a valid endpoint\");\n\t\t\t}\n\n\t\t\treturn new LMStudioClient(lmStudioEndpoint, lmStudioModelName);\n\t\t}\n\n\t\tif (modelKind === ModelKind.OpenAI) {\n\t\t\tconst openAIModelName = await this.getOpenAIModelName();\n\t\t\tconst openAIKey = await this.getOpenAIKey();\n\t\t\tconst openAICustomEndpoint = await this.getOpenAICustomEndpoint();\n\n\t\t\tif (!openAIKey) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"When using OpenAI in a bring your own key configuration, you must provide a valid token\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn new OpenAIClient(openAIKey, openAIModelName, openAICustomEndpoint);\n\t\t}\n\n\t\tif (modelKind === ModelKind.Anthropic) {\n\t\t\tconst anthropicModelName = await this.getAnthropicModelName();\n\t\t\tconst anthropicKey = await this.getAnthropicKey();\n\n\t\t\tif (!anthropicKey) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"When using Anthropic in a bring your own key configuration, you must provide a valid token\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn new AnthropicAIClient(anthropicKey, anthropicModelName);","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/apps/desktop/src/lib/ai/service.ts#L325-L361","documentation":"Thrown by AIService.buildClient when the selected model kind is OpenAI with a bring-your-own-key setup but no API key has been stored (getOpenAIKey returned empty). It is a configuration guard: the OpenAI client cannot be constructed without credentials, so the caller (aiClient) must prompt the user to enter an OpenAI key before retrying.","triggerScenarios":"User selects OpenAI as the AI provider without entering an API key in settings.","commonSituations":"Chose OpenAI but skipped the key field; key was cleared on settings reset; assumed the app would use its own credentials when BYO-key mode is active.","solutions":["Enter a valid OpenAI API key in the AI settings.","Create a key at platform.openai.com if you don't have one.","Alternatively switch to a provider that doesn't need a key (GitButler API while logged in, or a local model)."],"exampleFix":"// before\nopenAIKey: ''\n// after\nopenAIKey: 'sk-...' // valid OpenAI API key","handlingStrategy":"validation","validationCode":"const key = await aiService.getOpenAIKey();\nif (!key) {\n  // prompt for the OpenAI API key before invoking AI features\n}","typeGuard":null,"tryCatchPattern":"try {\n  await aiService.summarize(...);\n} catch (e) {\n  if (e.message.includes('OpenAI') && e.message.includes('valid token')) {\n    // open settings to collect the OpenAI API key\n  } else {\n    throw e;\n  }\n}","preventionTips":["Enter the OpenAI API key immediately when choosing the OpenAI provider.","Validate key format (starts with 'sk-') when saving settings.","Offer a provider switch fallback when no key is present."],"tags":["configuration","api-key","openai"],"backgroundTag":"missing-api-key","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}