Hmbown/CodeWhale · error
{timeout_message}
Error message
{timeout_message} What it means
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.
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.
Defensive patterns
Strategy: retry
Try / catch
match auth.login_device_code() {
Err(e) if e.to_string().contains("timed out") => {
eprintln!("Device code expired; restarting login with a fresh code.");
auth.login_device_code()?;
}
other => other?,
} Prevention
- 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
When it happens
Trigger: 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`.
Common situations: User abandoned the browser step, the verification code expired, or the machine was suspended during authorization.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- {}
- {message}
- returned an unusable verification URI
- offers no device-code flow; sign in through the browser…
- offers no browser sign-in flow; sign in through the…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/953721570941fda1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/config/src/device_code.rs:174
};
}
}
// Never sleep past the code's expiry, even after slow_down backoff.
let remaining = deadline.saturating_duration_since(Instant::now());
if remaining.is_zero() {
break;
}
sleep(interval.min(remaining));
}
Err(self.timed_out(saw_slow_down))
}
fn timed_out(&self, saw_slow_down: bool) -> anyhow::Error {
match (saw_slow_down, self.slow_down_timeout_message.as_deref()) {
(true, Some(message)) => anyhow::anyhow!("{message}"),
_ => anyhow::anyhow!("{}", self.timeout_message),
}
}
}
/// Reject a device-code verification URI that must not be handed to a browser
/// opener.
///
/// Ported from pi's `validateVerificationUri`
/// (`packages/ai/src/auth/oauth/xai.ts`, MIT, Copyright (c) 2025 Mario
/// Zechner): the URI comes straight off the wire and is passed to the platform
/// "open this" call, so a malicious or compromised response could otherwise
/// launch `file:`, a custom app scheme, or a helper with attacker-chosen
/// arguments. pi requires `https:`; Codewhale additionally allows `http:` on a
/// loopback host, which is what self-hosted issuers and the device-code tests
/// use — matching the loopback allowance the account login already makes.
///
/// Embedded credentials are rejected in every case.
pub fn validate_browser_verification_uri(raw: &str, context: &str) -> Result<String> {View on GitHub (pinned to 73e0f67d83)