gitbutlerapp/gitbutler · error

When using OpenAI in a bring your own key configuration…

Error message

When using OpenAI in a bring your own key configuration, you must provide a valid token

What it means

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.

Solutions

  1. Enter a valid OpenAI API key in the AI settings.
  2. Create a key at platform.openai.com if you don't have one.
  3. Alternatively switch to a provider that doesn't need a key (GitButler API while logged in, or a local model).

Example fix

// before
openAIKey: ''
// after
openAIKey: 'sk-...' // valid OpenAI API key
Defensive patterns

Strategy: validation

Validate before calling

const key = await aiService.getOpenAIKey();
if (!key) {
  // prompt for the OpenAI API key before invoking AI features
}

Try / catch

try {
  await aiService.summarize(...);
} catch (e) {
  if (e.message.includes('OpenAI') && e.message.includes('valid token')) {
    // open settings to collect the OpenAI API key
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: User selects OpenAI as the AI provider without entering an API key in settings.

Common situations: 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.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/8692d483f648c70d. Report an issue: GitHub.

Appendix: source

Thrown at apps/desktop/src/lib/ai/service.ts:343

		if (modelKind === ModelKind.LMStudio) {
			const lmStudioEndpoint = await this.getLMStudioEndpoint();
			const lmStudioModelName = await this.getLMStudioModelName();

			if (!lmStudioEndpoint) {
				throw new Error("When using LM Studio, you must provide a valid endpoint");
			}

			return new LMStudioClient(lmStudioEndpoint, lmStudioModelName);
		}

		if (modelKind === ModelKind.OpenAI) {
			const openAIModelName = await this.getOpenAIModelName();
			const openAIKey = await this.getOpenAIKey();
			const openAICustomEndpoint = await this.getOpenAICustomEndpoint();

			if (!openAIKey) {
				throw new Error(
					"When using OpenAI in a bring your own key configuration, you must provide a valid token",
				);
			}

			return new OpenAIClient(openAIKey, openAIModelName, openAICustomEndpoint);
		}

		if (modelKind === ModelKind.Anthropic) {
			const anthropicModelName = await this.getAnthropicModelName();
			const anthropicKey = await this.getAnthropicKey();

			if (!anthropicKey) {
				throw new Error(
					"When using Anthropic in a bring your own key configuration, you must provide a valid token",
				);
			}

			return new AnthropicAIClient(anthropicKey, anthropicModelName);

View on GitHub (pinned to 58e5313667)