cube-js/cube · error
device code expired before it was authorized; run `cube logi
Error message
device code expired before it was authorized; run `cube login` again
What it means
During the OAuth2 device-code flow (`cube login`), the CLI polls the token endpoint until the user completes browser authorization. This error is raised when the polling loop's deadline — computed as now + device.expires_in seconds from the device authorization response — is reached before approval. The device code is single-use and time-boxed per RFC 8628, so once it lapses the CLI cannot obtain a token and the user must restart the login.
Source
Thrown at rust/cube-cli/src/oauth.rs:129
"could not parse device authorization response: {e}\n{text}"
))
})
}
/// Step 3 — poll the token endpoint until the user approves (or it fails).
pub async fn poll_for_token(
http: &reqwest::Client,
url: &str,
cfg: &OAuthConfig,
device: &DeviceAuthorization,
) -> Result<TokenResponse> {
let endpoint = format!("{}{}", base(url), TOKEN_PATH);
let deadline = Instant::now() + Duration::from_secs(device.expires_in);
let mut interval = device.interval.max(1);
loop {
if Instant::now() >= deadline {
bail!("device code expired before it was authorized; run `cube login` again");
}
tokio::time::sleep(Duration::from_secs(interval)).await;
let mut form = vec![
("grant_type", DEVICE_CODE_GRANT),
("device_code", device.device_code.as_str()),
("client_id", cfg.client_id.as_str()),
];
if let Some(secret) = &cfg.client_secret {
form.push(("client_secret", secret));
}
// Transient network failures (server redeploy, flaky connection) must
// not abort the login — keep polling until the device code expires.
let res = match http.post(&endpoint).form(&form).send().await {
Ok(res) => res,
Err(_) => continue,
};
let status = res.status();View on GitHub (pinned to 7d981676b3)
Solutions
- Run `cube login` again and complete the browser authorization promptly
- Open the verification URL and enter the device code as soon as it is displayed
- Check that the auth server (url in OAuthConfig) is reachable — failed polls are retried until expiry, and persistent network failures will silently burn the whole window
- If expiry happens consistently fast, verify the OAuth provider's device-code TTL configuration
Example fix
// before (expired — no token) cube login // ...waited 20 minutes... // after: re-run and authorize immediately cube login // open https://cloud.cube.dev/login/device and enter the code now
Defensive patterns
Strategy: retry
Prevention
- Complete the browser authorization immediately after running `cube login`
- Keep the printed verification URL open before the code expires
- Ensure stable connectivity to the auth server during login so polling isn't stalled until expiry
- Avoid long `slow_down` backoff chains by approving on the first or second prompt
When it happens
Trigger: Raised in poll_for_token when Instant::now() >= deadline (elapsed device.expires_in seconds), or when the token endpoint returns the `expired_token` error code (see also error 672). Typical cause: the user did not open the verification URL and enter the code before expiry.
Common situations: User walked away after `cube login` printed the code; short expires_in from the auth server; clock skew is irrelevant here (monotonic Instant), but slow polling start after long `slow_down` backoffs (interval grows by 5s each slow_down) can consume the budget.
Related errors
- authorization was denied in the browser
- authorization failed: {other}{}
- Provided token isn't for ${dotCubeCloud.url}
- Failed to get access token: ${res.statusText}
- nothing is building branch {branch} (status {status}{}). If
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/00cd01e63e791272.
Report an issue: GitHub.