{"record":{"id":"dd522e5f341150a8","repo":"jlcodes99/cockpit-tools","slug":"codex-oauth-login-id-callback-url-el","errorCode":null,"errorMessage":"Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s","messagePattern":"Codex OAuth 回调超时: login_id=(.+?), callback_url=(.+?), elapsed=(.+?)s","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/cockpit-core/src/modules/codex_oauth.rs","lineNumber":690,"sourceCode":"    loop {\n        let should_stop = {\n            let oauth_state = OAUTH_STATE.lock().unwrap();\n            match oauth_state.as_ref() {\n                Some(state) => state.state != expected_state || state.login_id != expected_login_id,\n                None => true,\n            }\n        };\n\n        if should_stop {\n            logger::log_info(&format!(\n                \"Codex OAuth 已取消或状态已变更，停止回调监听: login_id={}\",\n                expected_login_id\n            ));\n            break;\n        }\n\n        if start.elapsed() > timeout {\n            logger::log_error(&format!(\n                \"Codex OAuth 回调超时: login_id={}, callback_url={}, elapsed={}s\",\n                expected_login_id,\n                callback_url,\n                start.elapsed().as_secs()\n            ));\n            clear_state_on_exit = true;\n            break;\n        }\n\n        if let Ok(Some(request)) = server.try_recv() {\n            let url = request.url().to_string();\n\n            if url.starts_with(\"/auth/callback\") {\n                let has_query = url.contains('?');\n                logger::log_info(&format!(\n                    \"Codex OAuth 收到回调请求: login_id={}, path=/auth/callback, has_query={}\",\n                    expected_login_id, has_query\n                ));","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/crates/cockpit-core/src/modules/codex_oauth.rs#L672-L708","documentation":"start_callback_server waits for the OAuth provider to redirect to the local callback URL. If no callback arrives within the configured timeout, it logs this message (including login_id, callback URL and elapsed seconds), sets clear_state_on_exit, and aborts the login. The OAuth session is abandoned rather than waiting forever.","triggerScenarios":"User does not complete browser sign-in before the timeout; the browser tab was closed or the redirect never reached 127.0.0.1:<port>; expected_login_id mismatch causes the loop to end and the elapsed time check then fires.","commonSituations":"Slow/failed provider login page; user switched away and forgot the browser step; corporate proxy intercepting the redirect; pop-up blocked so the auth page never opened.","solutions":["Restart the OAuth login (start_oauth_login) and complete the browser authentication promptly","Ensure the browser can reach the redirect URI (http://localhost:<port>/...) and pop-ups are allowed","Check that no proxy/VPN intercepts localhost redirects","Verify login_id/state match — a stale pending session may need clearing before retrying"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match start_oauth_login(app).await {\n    Err(e) if format!(\"{e}\").contains(\"回调超时\") => {\n        // state was cleared; prompt user to retry and complete browser step quickly\n        start_oauth_login(app).await\n    }\n    other => other,\n}","preventionTips":["Complete the browser sign-in promptly after starting the login","Disable pop-up blockers for the provider's auth domain","Ensure proxies/VPNs don't intercept localhost redirects","Keep the browser tab open until the app confirms login"],"tags":["oauth","codex","timeout","callback"],"backgroundTag":"oauth-callback-timeout","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}