gitbutlerapp/gitbutler · error

Enter an Anthropic API key

Error message

Enter an Anthropic API key

What it means

Validation error from `validate_update` (called by `update_ai_configuration`): an Anthropic provider configuration using the BringYourOwn credential option requires an API key, but none was submitted and none exists in storage. Prevents saving an Anthropic configuration that could not authenticate.

Solutions

  1. Provide a non-empty `anthropic_api_key` in the update request
  2. Keep the stored key (an existing key satisfies the check) instead of clearing it
  3. Switch `anthropic.key_option` to a non-BringYourOwn credential source
  4. Ensure the submitted key is not blank/whitespace

Example fix

// before
await api.updateAiConfiguration({ provider: "Anthropic", anthropic: { keyOption: "BringYourOwn" } });
// after
await api.updateAiConfiguration({
  provider: "Anthropic",
  anthropic: { keyOption: "BringYourOwn" },
  anthropicApiKey: process.env.ANTHROPIC_API_KEY,
});
Defensive patterns

Strategy: validation

Validate before calling

if (cfg.provider === "anthropic" && cfg.anthropic.keyOption === "BringYourOwn" &&
    !update.anthropicApiKey?.trim() && !(await api.hasStoredAnthropicKey())) {
  throw new Error("anthropic api key required before saving");
}

Type guard

function hasAnthropicKey(u: AiConfigUpdate): boolean {
  return typeof u.anthropicApiKey === "string" && u.anthropicApiKey.trim().length > 0;
}

Try / catch

try {
  await api.updateAiConfiguration(update);
} catch (e) {
  if (String(e).includes("Enter an Anthropic API key")) {
    setFieldError("anthropicApiKey", "required for BringYourOwn credential mode");
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling the AI configuration update with provider=anthropic, anthropic.key_option=BringYourOwn, empty/absent `anthropic_api_key` in the update payload, and no previously stored Anthropic key.

Common situations: Switching provider to Anthropic without entering a key; clearing the key field and saving; wiping the credential store then attempting to update settings.

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/a397ce8cb57f1255. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-api/src/ai.rs:188

    update: &AiConfigurationUpdate,
    openai_has_key: bool,
    anthropic_has_key: bool,
) -> Result<()> {
    let configuration = domain_configuration(update, DomainConfiguration::default())?;

    if configuration.provider == LLMProviderKind::OpenAi
        && configuration.openai.key_option == CredentialsKeyOption::BringYourOwn
        && submitted_key(update.openai_api_key.clone()).is_none()
        && !openai_has_key
    {
        bail!("Enter an OpenAI API key")
    }
    if configuration.provider == LLMProviderKind::Anthropic
        && configuration.anthropic.key_option == CredentialsKeyOption::BringYourOwn
        && submitted_key(update.anthropic_api_key.clone()).is_none()
        && !anthropic_has_key
    {
        bail!("Enter an Anthropic API key")
    }
    Ok(())
}

fn domain_configuration(
    update: &AiConfigurationUpdate,
    mut configuration: DomainConfiguration,
) -> Result<DomainConfiguration> {
    configuration.provider = provider(&update.provider)?;
    configuration.openai = OpenAiConfiguration {
        key_option: key_option("OpenAI", &update.openai_key_option)?,
        model: update.openai_model.clone(),
        custom_endpoint: update.openai_custom_endpoint.clone(),
    };
    configuration.anthropic = AnthropicConfiguration {
        key_option: key_option("Anthropic", &update.anthropic_key_option)?,
        model: update.anthropic_model.clone(),
    };

View on GitHub (pinned to 58e5313667)