{"record":{"id":"97bf58a3b33c83fd","repo":"gitbutlerapp/gitbutler","slug":"unsupported-ai-provider-value","errorCode":null,"errorMessage":"Unsupported AI provider '{value}'","messagePattern":"Unsupported AI provider '(.+?)'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/but-napi/src/ai.rs","lineNumber":108,"sourceCode":"        anthropic_model: configuration.anthropic.model,\n        anthropic_has_api_key,\n        ollama_endpoint: configuration.ollama.endpoint,\n        ollama_model: configuration.ollama.model,\n        lmstudio_endpoint: configuration.lmstudio.endpoint,\n        lmstudio_model: configuration.lmstudio.model,\n        is_configured,\n    })\n}\n\nfn provider(value: &str) -> Result<LLMProviderKind> {\n    match LLMProviderKind::from_git_config_value(value) {\n        Some(\n            provider @ (LLMProviderKind::OpenAi\n            | LLMProviderKind::Anthropic\n            | LLMProviderKind::Ollama\n            | LLMProviderKind::LMStudio),\n        ) => Ok(provider),\n        _ => bail!(\"Unsupported AI provider '{value}'\"),\n    }\n}\n\nfn key_option(provider: &str, value: &str) -> Result<CredentialsKeyOption> {\n    CredentialsKeyOption::from_git_config_value(value)\n        .with_context(|| format!(\"Unsupported {provider} credential source '{value}'\"))\n}\n\nfn submitted_key(value: Option<String>) -> Option<String> {\n    value.and_then(|value| {\n        let value = value.trim();\n        (!value.is_empty()).then(|| value.to_string())\n    })\n}\n\nfn validate_update(\n    update: &AiConfigurationUpdate,\n    openai_has_key: bool,","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-napi/src/ai.rs#L90-L126","documentation":"The but-napi AI configuration maps a provider string onto `LLMProviderKind` via `from_git_config_value`. Only OpenAi, Anthropic, Ollama, and LMStudio are accepted; every other string — including near-misses and providers the domain enum may know but NAPI does not expose — is rejected by `provider()`.","triggerScenarios":"Calling the AI configuration update through NAPI with `update.provider` set outside the supported set: typos like 'openai ' with whitespace, 'azure-openai', 'google', or an empty string.","commonSituations":"A frontend whose provider list is newer or older than the installed native module; users hand-editing the provider value in git config; provider ids copy-pasted from other tools.","solutions":["Set provider to one of OpenAI, Anthropic, Ollama, or LMStudio using the exact spelling `from_git_config_value` accepts","Update the app/JS layer so its provider list matches the installed native module version","Trim whitespace and fix casing in the value before submitting the update"],"exampleFix":"// before\nawait ai.updateAiConfig({ provider: 'azure-openai' }); // bails\n\n// after: one of the supported provider ids\nawait ai.updateAiConfig({ provider: 'openai' }); // openai | anthropic | ollama | lmstudio","handlingStrategy":"validation","validationCode":"// TypeScript: validate against the supported provider set before the call\nconst SUPPORTED_PROVIDERS = ['openai', 'anthropic', 'ollama', 'lmstudio'] as const;\nif (!SUPPORTED_PROVIDERS.includes(update.provider as never)) {\n  throw new Error(`Unsupported AI provider '${update.provider}'`);\n}\nawait ai.updateAiConfig(update);","typeGuard":"// TypeScript\nconst SUPPORTED_PROVIDERS = ['openai', 'anthropic', 'ollama', 'lmstudio'] as const;\ntype SupportedProvider = (typeof SUPPORTED_PROVIDERS)[number];\nfunction isSupportedProvider(v: string): v is SupportedProvider {\n  return (SUPPORTED_PROVIDERS as readonly string[]).includes(v.trim().toLowerCase());\n}","tryCatchPattern":"Catch the NAPI error, read the unsupported value from the message, and re-render the provider selector constrained to the supported list (aligned with the installed native module version).","preventionTips":["Source the provider list from the installed native module/SDK instead of hardcoding it in the frontend","Trim and normalize user-entered provider values before submitting"],"tags":["ai","llm","provider","config-validation","napi"],"backgroundTag":"unsupported-enum-value","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}