nikivdev/code · error

device code invalid. Run `f auth` again.

Error message

device code invalid. Run `f auth` again.

What it means

In `login` (src/auth.rs:101), the OAuth device-flow poll loop asks the auth server for the device-code status; when the server replies with status "invalid" the CLI bails with this message. It means the device code or user code the server received was rejected — typically it was already consumed, revoked, or mistyped. The remedy is to restart `f auth` to get a fresh code.

Source

Thrown at src/auth.rs:101

            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."),
            other => bail!("unexpected auth status: {}", other),
        }
    }

    bail!("device code expired. Run `f auth` again.")
}

fn open_in_browser(url: &str) {
    #[cfg(target_os = "macos")]
    {
        let _ = std::process::Command::new("open").arg(url).status();
    }

    #[cfg(target_os = "linux")]
    {
        let _ = std::process::Command::new("xdg-open").arg(url).status();
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `f auth` again to get a fresh device code
  2. Complete browser authorization promptly instead of leaving the prompt idle
  3. Avoid running two `f auth` sessions concurrently
  4. Check the auth server URL configured for Flow AI is current

Example fix

// before
bail!("device code invalid. Run `f auth` again.");
// after
// automatic re-request of a fresh device code instead of failing:
// let (code, url) = start_device_flow(...)?; continue;
bail!("device code invalid. Run `f auth` again."); // unchanged: manual restart is the intended UX
Defensive patterns

Strategy: try-catch

Try / catch

// Rust caller
match f_auth_login() {
    Err(e) if e.to_string().contains("device code invalid") => {
        eprintln!("Code rejected — restarting device flow...");
        f_auth_login()?; // retry once with a fresh code
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `f auth`, the poll endpoint returns status "invalid" — e.g. the device code expired and was reaped, the code was already redeemed by a prior login, or the server invalidated the session mid-poll.

Common situations: User leaves the auth prompt open too long, runs `f auth` twice in parallel and one redeems the code, or the auth server rotates/invalidates codes after a version change or clock drift.

Related errors


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