{"record":{"id":"180ab91c84a75935","repo":"Hmbown/CodeWhale","slug":"custom-provider-route-name-api-key-not-found","errorCode":null,"errorMessage":"Custom provider '{route_name}' API key not found: the route binds api_key_env = \"{env_name}\" but that environment variable is not set. Set {env_name} to your key, or remove api_key_env from [providers.{route_name}] to run the endpoint without credentials.","messagePattern":"Custom provider '(.+?)' API key not found: the route binds api_key_env = \"(.+?)\" but that environment variable is not set\\. Set (.+?) to your key, or remove api_key_env from \\[providers\\.(.+?)\\] to run the endpoint without credentials\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":7226,"sourceCode":"        // `[providers.<name>] api_key_env = \"...\"`. This remains safe for a\n        // custom endpoint because the binding belongs to that route; ambient\n        // provider variables below do not.\n        //\n        // For a custom provider, a binding that names an unset (or empty)\n        // variable is a broken credential contract, not a keyless route: fail\n        // loudly with the route-scoped fix instead of silently degrading to\n        // the self-hosted loopback keyless fallback below (#5104). Without\n        // this, an `api_key_env` route on a loopback host dispatched\n        // unauthenticated while the operator believed credentials were wired,\n        // and the composer-side preflight recovery never saw an error.\n        if provider == ApiProvider::Custom\n            && let Some(env_name) = bound_provider_api_key_env_name(self, provider)\n        {\n            return match std::env::var(&env_name) {\n                Ok(value) if !value.trim().is_empty() => Ok(value),\n                _ => {\n                    let route_name = self.provider.as_deref().unwrap_or(\"<name>\");\n                    Err(anyhow::anyhow!(\n                        \"Custom provider '{route_name}' API key not found: the route binds \\\n                         api_key_env = \\\"{env_name}\\\" but that environment variable is not set. \\\n                         Set {env_name} to your key, or remove api_key_env from \\\n                         [providers.{route_name}] to run the endpoint without credentials.\"\n                    ))\n                }\n            };\n        }\n        if let Some(value) = provider_config_env_api_key(self, provider) {\n            return Ok(value);\n        }\n\n        // 2. The dispatcher resolves this same provider slot before launching\n        // the TUI. Standalone `codewhale-tui` launches must see the identical\n        // durable credential. Auto-detection is file-backed and prompt-free by\n        // default; the OS keyring is queried only when the user explicitly\n        // selects the system backend.\n        if !self.should_skip_secret_store_for_provider(provider)","sourceCodeStart":7208,"sourceCodeEnd":7244,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/config.rs#L7208-L7244","documentation":"Thrown during route resolution for a custom provider whose configuration binds `api_key_env` to an environment variable that is unset (or set to whitespace only). The message names the route, the env var, and both remedies: export the variable, or drop `api_key_env` to run the endpoint without credentials.","triggerScenarios":"Starting a session or switching routes to a custom provider `[providers.<name>]` that declares `api_key_env = \"...\"` while `std::env::var` on that name fails or returns an empty/whitespace value.","commonSituations":"Exporting the key in one shell but launching the app from another; missing the variable in a service/tmux environment; a typo in the `api_key_env` name versus the actual exported variable; CI environments where secrets are not injected.","solutions":["Set the variable: `export <env_name>=<your-key>` in the shell that launches the app","If the endpoint needs no auth, remove the `api_key_env` line from `[providers.<route_name>]` in your config","Verify the spelling of `api_key_env` matches the exported variable exactly (`echo \"${<env_name>}\"` to confirm it is non-empty)"],"exampleFix":"# before (config)\n[providers.myroute]\napi_key_env = \"MYROUTE_API_KEY\"\n# after — in the launching shell\nexport MYROUTE_API_KEY=\"sk-...\"","handlingStrategy":"validation","validationCode":"let env_name = \"MYROUTE_API_KEY\";\nif std::env::var(env_name).map_or(true, |v| v.trim().is_empty()) {\n    eprintln!(\"{env_name} is not set; the custom provider route will fail to resolve\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Export API keys in the same shell/scope that launches the app (or use an env file the launcher sources)","Grep the config for `api_key_env` at startup in scripts and assert each named variable is non-empty","Avoid whitespace-only values; quote the key when exporting","Remove `api_key_env` for endpoints that genuinely need no credentials"],"tags":["api-key","env-var","provider","config"],"backgroundTag":"missing-api-key","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"}