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

  1. Run `cube login` again and complete the browser authorization promptly
  2. Open the verification URL and enter the device code as soon as it is displayed
  3. 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
  4. 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

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


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/00cd01e63e791272. Report an issue: GitHub.