{"record":{"id":"799bfcf616848b63","repo":"tinyhumansai/openhuman","slug":"chat-factory-openai-oauth-lookup-failed-e","errorCode":null,"errorMessage":"[chat-factory] openai oauth lookup failed: {e}","messagePattern":"\\[chat-factory\\] openai oauth lookup failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/factory.rs","lineNumber":2609,"sourceCode":"        );\n        return Ok(key);\n    }\n\n    // OAuth fallback for `openai` runs only after standard API-key resolution\n    // returns empty, so env/audit/metrics in the standard path always execute\n    // and the OAuth path never silently bypasses provider-agnostic logic.\n    if slug == \"openai\" {\n        match crate::openhuman::inference::openai_oauth::lookup_openai_bearer_token(config) {\n            Ok(Some(token)) if !token.is_empty() => {\n                log::debug!(\n                    \"[providers][chat-factory] auth lookup slug={} key_present=true (oauth)\",\n                    slug\n                );\n                return Ok(token);\n            }\n            Ok(_) => {}\n            Err(e) => {\n                return Err(anyhow::anyhow!(\n                    \"[chat-factory] openai oauth lookup failed: {e}\"\n                ));\n            }\n        }\n    }\n\n    // Fallback: read from top-level config.api_key (direct config.toml api_key).\n    // This handles the case where a key was set in config.toml but not saved\n    // through the UI into auth-profiles.json.\n    //\n    // Scoped to the legacy direct-inference provider only — the cloud-provider\n    // slug whose endpoint matches `config.inference_url`. `config.api_key` was\n    // historically paired with `inference_url` for direct endpoint routing, so\n    // an unscoped fallback would leak this global key to any other provider\n    // whose auth-profile lookup returned empty (cross-provider credential leak\n    // flagged by CodeRabbit + maintainers on #2724).\n    if legacy_inference_slug(config) == Some(slug) {\n        if let Some(config_key) = config.api_key.as_ref() {","sourceCodeStart":2591,"sourceCodeEnd":2627,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/factory.rs#L2591-L2627","documentation":"The OpenAI OAuth bearer-token lookup (openai_oauth::lookup_openai_bearer_token) failed while resolving credentials for slug 'openai'. This path runs only after standard API-key resolution returned empty, so both the API key and the OAuth token are unavailable or the OAuth store itself errored.","triggerScenarios":"Thrown at src/openhuman/inference/provider/factory.rs:2609 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Sign in again via the OpenAI OAuth flow to refresh the stored token","Provide an OpenAI API key through the standard credential path instead of OAuth","Inspect the underlying error for an expired/missing token file or keyring failure"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}