{"record":{"id":"953721570941fda1","repo":"Hmbown/CodeWhale","slug":"timeout-message","errorCode":null,"errorMessage":"{timeout_message}","messagePattern":"\\{timeout_message\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/device_code.rs","lineNumber":174,"sourceCode":"                    };\n                }\n            }\n\n            // Never sleep past the code's expiry, even after slow_down backoff.\n            let remaining = deadline.saturating_duration_since(Instant::now());\n            if remaining.is_zero() {\n                break;\n            }\n            sleep(interval.min(remaining));\n        }\n\n        Err(self.timed_out(saw_slow_down))\n    }\n\n    fn timed_out(&self, saw_slow_down: bool) -> anyhow::Error {\n        match (saw_slow_down, self.slow_down_timeout_message.as_deref()) {\n            (true, Some(message)) => anyhow::anyhow!(\"{message}\"),\n            _ => anyhow::anyhow!(\"{}\", self.timeout_message),\n        }\n    }\n}\n\n/// Reject a device-code verification URI that must not be handed to a browser\n/// opener.\n///\n/// Ported from pi's `validateVerificationUri`\n/// (`packages/ai/src/auth/oauth/xai.ts`, MIT, Copyright (c) 2025 Mario\n/// Zechner): the URI comes straight off the wire and is passed to the platform\n/// \"open this\" call, so a malicious or compromised response could otherwise\n/// launch `file:`, a custom app scheme, or a helper with attacker-chosen\n/// arguments. pi requires `https:`; Codewhale additionally allows `http:` on a\n/// loopback host, which is what self-hosted issuers and the device-code tests\n/// use — matching the loopback allowance the account login already makes.\n///\n/// Embedded credentials are rejected in every case.\npub fn validate_browser_verification_uri(raw: &str, context: &str) -> Result<String> {","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/device_code.rs#L156-L192","documentation":"The default branch of `timed_out`: when the device-code polling loop (`run`) exhausts its time budget without an explicit slow-down-specific message (either no slow_down occurred, or no `slow_down_timeout_message` is configured), the generic `timeout_message` is returned. This is the standard 'you took too long to authorize' error of the device flow.","triggerScenarios":"The device-code flow's polling loop reaches its overall expiry (user never entered the code, or polling ran past `expires_in`) — called from `run`.","commonSituations":"User abandoned the browser step, the verification code expired, or the machine was suspended during authorization.","solutions":["Re-run the device-code login to get a fresh code and complete it within the expiry window.","Authorize immediately after the code is displayed — codes typically expire within minutes.","Avoid suspending the machine mid-login; if interrupted, restart the flow."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match auth.login_device_code() {\n    Err(e) if e.to_string().contains(\"timed out\") => {\n        eprintln!(\"Device code expired; restarting login with a fresh code.\");\n        auth.login_device_code()?;\n    }\n    other => other?,\n}","preventionTips":["Complete device authorization within the expiry window (usually minutes)","Avoid machine suspend during the login flow","Automate re-prompting for a fresh code on timeout instead of retrying the old one"],"tags":["oauth","device-code","timeout"],"backgroundTag":"request-timeout","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"}