nikivdev/code · error

device auth poll failed: HTTP {}

Error message

device auth poll failed: HTTP {}

What it means

During the device-auth login loop, each poll of the token endpoint must return 2xx. A non-2xx poll response aborts the whole login with this error. Note that OAuth-style 'slow_down'/'authorization_pending' hints are expected as 200-with-status-body in this implementation; an HTTP-level failure here means something is wrong with the request or the service.

Source

Thrown at src/auth.rs:83

    open_in_browser(&payload.verification_url);

    let expires_at = Instant::now() + Duration::from_secs(payload.expires_in);
    let poll_url = format!("{}/api/auth/cli/poll", api_url);

    println!("Waiting for approval...");

    while Instant::now() < expires_at {
        sleep(Duration::from_secs(payload.interval.max(1)));

        let poll_response = client
            .post(&poll_url)
            .json(&serde_json::json!({"device_code": payload.device_code}))
            .send()
            .context("failed to poll device auth")?;

        if !poll_response.status().is_success() {
            bail!("device auth poll failed: HTTP {}", poll_response.status());
        }

        let poll: DevicePollResponse = poll_response
            .json()
            .context("failed to parse device auth poll response")?;

        match poll.status.as_str() {
            "approved" => {
                let token = poll
                    .token
                    .ok_or_else(|| anyhow!("device auth approved without token"))?;
                env::save_ai_auth_token(token, Some(api_url.clone()))?;
                println!("✓ Auth complete. You're ready to use Flow AI.");
                return Ok(());
            }
            "pending" => continue,
            "expired" => bail!("device code expired. Run `f auth` again."),
            "invalid" => bail!("device code invalid. Run `f auth` again."),

View on GitHub (pinned to a747e741ae)

Solutions

  1. Check the status code (429 → back off and slow the poll interval; 4xx → re-run 'f auth' for a fresh device code; 5xx → retry after a delay)
  2. Increase the poll interval to respect rate limits before retrying
  3. Re-run the login to obtain a new device code if the current one is rejected
  4. Verify API base URL / endpoint configuration matches the auth server

Example fix

// before
if !poll_response.status().is_success() {
    bail!("device auth poll failed: HTTP {}", poll_response.status());
}
// after
if poll_response.status() == StatusCode::TOO_MANY_REQUESTS {
    interval = Duration::from_secs(interval.as_secs() * 2);
    continue;
}
if !poll_response.status().is_success() {
    bail!("device auth poll failed: HTTP {}", poll_response.status());
}
Defensive patterns

Strategy: retry

Validate before calling

// Poll with exponential backoff to avoid 429s
let mut interval = Duration::from_secs(5);
loop {
    std::thread::sleep(interval);
    interval = (interval * 2).min(Duration::from_secs(30));
    // ... send poll request
}

Try / catch

match login(&api_url) {
    Err(e) if e.to_string().contains("device auth poll failed") => {
        eprintln!("{}\nPolling failed; get a new code with `f auth`.", e);
    }
    other => other?,
}

Prevention

When it happens

Trigger: POST to poll_url with {"device_code": ...} returns 4xx/5xx: device code malformed/expired server-side, wrong poll URL, rate limiting (429), or auth service outage.

Common situations: Polling too aggressively triggers 429; network/proxy intermittent failures; device_code corrupted because the start response failed to parse fields; API version mismatch changing the poll endpoint.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/66278489e801ff3e. Report an issue: GitHub.