{"record":{"id":"806cd99ed92454a9","repo":"Hmbown/CodeWhale","slug":"custom-provider-provider-name-has-no-auth-conf","errorCode":null,"errorMessage":"Custom provider '{provider_name}' has no auth configured.\nAdd api_key_env = \"YOUR_ENV_VAR\" (or api_key) to [providers.{provider_name}] in ~/.codewhale/config.toml.","messagePattern":"Custom provider '(.+?)' has no auth configured\\.\nAdd api_key_env = \"YOUR_ENV_VAR\" \\(or api_key\\) to \\[providers\\.(.+?)\\] in ~/\\.codewhale/config\\.toml\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":7454,"sourceCode":"                )\n            }\n            // Custom OpenAI-compatible endpoints (#1519): the key comes from the\n            // env var named by `[providers.<name>] api_key_env`. If we reached\n            // here it is unset/empty (and the endpoint is not loopback).\n            ApiProvider::Custom => {\n                let provider_name = self.provider.as_deref().unwrap_or(\"<name>\");\n                match self\n                    .provider_config_for(provider)\n                    .and_then(|entry| entry.api_key_env.as_deref())\n                    .map(str::trim)\n                    .filter(|name| !name.is_empty())\n                {\n                    Some(env_name) => anyhow::bail!(\n                        \"Custom provider '{provider_name}' API key not found.\\n\\\n                         Set the environment variable {env_name} to your key, \\\n                         or add api_key to [providers.{provider_name}].\"\n                    ),\n                    None => anyhow::bail!(\n                        \"Custom provider '{provider_name}' has no auth configured.\\n\\\n                         Add api_key_env = \\\"YOUR_ENV_VAR\\\" (or api_key) to \\\n                         [providers.{provider_name}] in ~/.codewhale/config.toml.\"\n                    ),\n                }\n            }\n            _ => anyhow::bail!(\"{}\", missing_provider_api_key_message(provider)?),\n        }\n    }\n\n    /// Resolve the skills directory path.\n    #[must_use]\n    pub fn skills_dir(&self) -> PathBuf {\n        self.skills_dir\n            .as_deref()\n            .map(expand_path)\n            .or_else(default_skills_dir)\n            .unwrap_or_else(|| PathBuf::from(\"./skills\"))","sourceCodeStart":7436,"sourceCodeEnd":7472,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/config.rs#L7436-L7472","documentation":"Thrown for a custom provider that has no auth configuration at all: no usable api_key_env name and no inline api_key. It is the `None` arm of the custom-provider key lookup and instructs the user to declare one of the two supported auth fields in the provider's config table. Without it, requests would go out with no credential.","triggerScenarios":"A [providers.<name>] entry (or the provider being referenced) defines a base URL but neither api_key nor api_key_env, and the provider is used for a request.","commonSituations":"Hand-written custom provider table missing the auth fields; copied config from a provider that used a different auth mechanism; typo'd key names (e.g. apikey, api-key).","solutions":["Add `api_key_env = \"YOUR_ENV_VAR\"` to [providers.<name>] in ~/.codewhale/config.toml and export that variable","Or add `api_key = \"...\"` directly to the [providers.<name>] table","Check for typos: the fields are exactly `api_key` and `api_key_env`"],"exampleFix":"// before\n[providers.acme]\nbase_url = \"https://api.acme.dev/v1\"\n// after\n[providers.acme]\nbase_url = \"https://api.acme.dev/v1\"\napi_key_env = \"ACME_API_KEY\"","handlingStrategy":"validation","validationCode":"// check the custom provider table declares auth before use\n// config.toml must contain, under [providers.<name>]: api_key or api_key_env\nlet cfg = std::fs::read_to_string(\"~/.codewhale/config.toml\")?;\nlet has_auth = cfg.contains(\"api_key\") || cfg.contains(\"api_key_env\");\nif !has_auth { eprintln!(\"custom provider has no auth configured\"); }","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"has no auth configured\") => add_api_key_field_to_provider_table(),\n    other => other?,\n}","preventionTips":["Always pair a custom base_url with api_key or api_key_env","Copy a working provider table as a template","Validate config after hand edits"],"tags":["authentication","config","custom-provider","missing-config"],"backgroundTag":"missing-required-config-field","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}