{"record":{"id":"50c3a1f8b8a235b1","repo":"Hmbown/CodeWhale","slug":"codex-oauth-credentials-are-only-available-on-the","errorCode":null,"errorMessage":"Codex OAuth credentials are only available on the official OpenAI Codex route","messagePattern":"Codex OAuth credentials are only available on the official OpenAI Codex route","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/config.rs","lineNumber":12325,"sourceCode":"\n/// Check whether the given provider has any usable API key — via env var,\n/// provider/root config. Used by the `/provider` picker to decide whether to\n/// prompt for a key inline.\n#[must_use]\npub fn has_api_key_for(config: &Config, provider: ApiProvider) -> bool {\n    credential_resolve::resolve_credential_source(config, provider).is_present()\n}\n\nimpl Config {\n    /// Resolve one coherent Codex OAuth snapshot. The bearer and account id\n    /// must come from the same secure file handle; opening the external JSON a\n    /// second time could pair identities across an atomic owner refresh or a\n    /// hostile path swap.\n    pub(crate) fn codex_credentials(&self) -> Result<crate::oauth::CodexCredentials> {\n        if let Some(credentials) = crate::oauth::credentials_from_env() {\n            return Ok(credentials);\n        }\n        anyhow::ensure!(\n            self.api_provider() == ApiProvider::OpenaiCodex\n                && !self.provider_uses_custom_endpoint(ApiProvider::OpenaiCodex),\n            \"Codex OAuth credentials are only available on the official OpenAI Codex route\"\n        );\n        if crate::oauth::credentials_valid(crate::oauth::OAuthProvider::Chatgpt, self) {\n            let owned =\n                crate::oauth::get_owned_credentials(crate::oauth::OAuthProvider::Chatgpt, self)?;\n            return Ok(crate::oauth::CodexCredentials {\n                access_token: owned.access_token,\n                account_id: owned.account_id,\n            });\n        }\n        let path = crate::oauth::auth_file_path();\n        let grant = self.external_credential_read_grant(\n            ApiProvider::OpenaiCodex,\n            codewhale_config::ExternalCredentialSource::CodexCli,\n            &path,\n        )?;","sourceCodeStart":12307,"sourceCodeEnd":12343,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/config.rs#L12307-L12343","documentation":"`codex_credentials()` only hands out Codex OAuth credentials when the active provider is the official OpenAI Codex route with the default endpoint (or when credentials come from the environment). Any other provider or a custom Codex endpoint is rejected to avoid pairing identities across an owner refresh or a hostile endpoint swap.","triggerScenarios":"Calling `config.codex_credentials()` while `api_provider() != OpenaiCodex`, or while a custom base URL is configured for the OpenaiCodex provider, and `credentials_from_env()` returned nothing.","commonSituations":"User switched to another provider (Anthropic, custom endpoint) but code or a command still requests Codex OAuth credentials; user pointed the Codex provider at a proxy/gateway URL; stale config after migrating between providers.","solutions":["Switch the active provider back to the official OpenAI Codex route and remove any custom endpoint override for it","If credentials should come from the environment, set the Codex OAuth env variables so `credentials_from_env()` succeeds","Re-run `codex auth`/OAuth login while on the official route so valid credentials are stored","Remove the custom `base_url` for the OpenaiCodex provider in the config file"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if config.api_provider() != ApiProvider::OpenaiCodex\n    || config.provider_uses_custom_endpoint(ApiProvider::OpenaiCodex) {\n    // route user back to official Codex route or use env credentials\n}","typeGuard":"fn codex_credentials_available(c: &Config) -> bool {\n    crate::oauth::credentials_from_env().is_some()\n        || (c.api_provider() == ApiProvider::OpenaiCodex\n            && !c.provider_uses_custom_endpoint(ApiProvider::OpenaiCodex))\n}","tryCatchPattern":"match config.codex_credentials() {\n    Err(e) if e.to_string().contains(\"only available on the official OpenAI Codex route\") => {\n        // switch provider or fall back to API-key auth\n    }\n    other => other?,\n}","preventionTips":["Check `api_provider()` before requesting Codex OAuth credentials","Do not set a custom endpoint for the OpenaiCodex provider if OAuth is needed","Provide Codex credentials via environment when running off the official route"],"tags":["oauth","codex","configuration","provider-routing"],"backgroundTag":"authentication-required","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"}