{"record":{"id":"27bce532b3662858","repo":"xai-org/grok-build","slug":"oidcerror-callbackchannelclosed","errorCode":null,"errorMessage":"OidcError::CallbackChannelClosed","messagePattern":"OidcError::CallbackChannelClosed","errorType":"exception","errorClass":"OidcError","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/auth/oidc/login.rs","lineNumber":286,"sourceCode":"            match parse_pasted_input(&code) {\n                Ok(result) => {\n                    tracing::debug!(\"OIDC: received code via client paste\");\n                    let _ = client_tx.send(Ok(result)).await;\n                    return;\n                }\n                Err(e) => {\n                    tracing::debug!(error = %e, \"OIDC: invalid client paste input\");\n                }\n            }\n        }\n    };\n\n    drop(tx);\n\n    let result = tokio::select! {\n        r = tokio::time::timeout(AUTH_CALLBACK_TIMEOUT, rx.recv()) => {\n            r.map_err(|_| anyhow::Error::new(OidcError::CallbackTimeout))?\n                .ok_or_else(|| anyhow::Error::new(OidcError::CallbackChannelClosed))?\n        }\n        _ = client_bridge => {\n            rx.recv().await\n                .ok_or_else(|| anyhow::Error::new(OidcError::CallbackChannelClosed))?\n        }\n    };\n\n    let _ = shutdown_tx.send(());\n    let _ = server.await;\n\n    result.map_err(|e| anyhow::Error::new(OidcError::CallbackAuthFailed(e)))\n}\n\n/// Race loopback callback against stdin paste.\nasync fn race_callback_and_stdin(\n    listener: TcpListener,\n    enable_stdin: bool,\n) -> anyhow::Result<Callback> {","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/auth/oidc/login.rs#L268-L304","documentation":"In `race_callback_and_client_ui`, when the timeout branch's inner `rx.recv()` returns None, the mpsc channel to the callback handler has been closed without ever producing an authorization code. The error distinguishes 'channel closed, no code' from an actual timeout: the callback receiver side dropped before delivering a code.","triggerScenarios":"AUTH_CALLBACK_TIMEOUT elapses is excluded here; specifically the timeout future completes Ok(None) — i.e. rx.recv() yields None because the sender (the loopback HTTP handler or client UI bridge) was dropped without sending a code.","commonSituations":"The loopback server task panicked or was aborted after shutdown_tx fired; the browser hit /callback with a malformed request and the handler dropped tx without sending; the client UI bridge shut down the flow early.","solutions":["Retry the login; transient handler shutdowns are usually resolved by a fresh run.","Check server logs for the loopback callback handler panicking or rejecting the request (e.g. missing code/state query params).","Verify the IDP redirects back with the expected `code` (and `state`) query parameters; a misconfigured redirect_uri can yield an error response that closes the channel.","If the client UI bridge is shutting down the flow, confirm the UI stays alive until login completes."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_channel_closed(err: &anyhow::Error) -> bool {\n    err.downcast_ref::<OidcError>()\n        .map_or(false, |e| matches!(e, OidcError::CallbackChannelClosed))\n}","tryCatchPattern":"if is_channel_closed(&err) {\n    tracing::warn!(\"callback channel closed before code delivery; retrying login\");\n    return run_login_flow(config, auth_manager, channels).await; // one retry\n}","preventionTips":["Keep the client UI open until login completes","Verify the IDP redirect includes `code` and `state` query params","Watch logs for loopback handler panics that drop the sender","Retry once before surfacing the error to the user"],"tags":["oidc","channel-closed","auth-flow"],"backgroundTag":"oauth-callback-channel-closed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}