nikivdev/code · error

device auth start failed: HTTP {}

Error message

device auth start failed: HTTP {}

What it means

The device-code login flow (login in auth.rs) first POSTs {"client":"flow"} to the device-auth start endpoint. Any non-2xx response aborts with this error, embedding the HTTP status. This happens before any polling or token exchange, so it indicates the auth server refused to initiate the flow.

Source

Thrown at src/auth.rs:54

    let api_url = api_url_override
        .or_else(|| env::load_ai_api_url().ok())
        .unwrap_or_else(|| "https://myflow.sh".to_string());
    let api_url = api_url.trim().trim_end_matches('/').to_string();

    let client = Client::builder()
        .timeout(Duration::from_secs(30))
        .build()
        .context("failed to create HTTP client for auth")?;

    let start_url = format!("{}/api/auth/cli/start", api_url);
    let response = client
        .post(&start_url)
        .json(&serde_json::json!({"client": "flow"}))
        .send()
        .context("failed to start device auth")?;

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

    let payload: DeviceStartResponse = response
        .json()
        .context("failed to parse device auth response")?;

    println!("\nFlow auth with myflow");
    println!("───────────────────────");
    println!("Code: {}", payload.user_code);
    println!("Open: {}\n", payload.verification_url);

    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...");

View on GitHub (pinned to a747e741ae)

Solutions

  1. Check the HTTP status in the message (404 → wrong URL/path, 401/403 → client blocked, 429 → rate limited, 5xx → server side)
  2. Verify the configured API base URL is correct for your environment (env var / config)
  3. Retry later if it's a 5xx/429 (server outage or rate limit)
  4. Inspect the response body via a manual curl of the start endpoint to see the server's error detail

Example fix

// before
if !response.status().is_success() {
    bail!("device auth start failed: HTTP {}", response.status());
}
// after
let status = response.status();
let body = response.text().unwrap_or_default();
bail!("device auth start failed: HTTP {} (body: {})", status, body);
Defensive patterns

Strategy: retry

Validate before calling

fn api_base_url_configured() -> Result<(), String> {
    match std::env::var("FLOW_API_URL") {
        Ok(url) if url.starts_with("http") => Ok(()),
        Ok(url) => Err(format!("FLOW_API_URL is not a valid http(s) URL: {}", url)),
        Err(_) => Err("FLOW_API_URL not set".to_string()),
    }
}

Try / catch

match login(&api_url) {
    Err(e) if e.to_string().contains("device auth start failed") => {
        eprintln!("{}\nCheck your API URL and network, then try again.", e);
    }
    other => other?,
}

Prevention

When it happens

Trigger: POST to start_url returns 4xx/5xx: auth server down, client blocked, wrong API base URL configured, rate limited, or endpoint path changed server-side.

Common situations: Misconfigured API URL (pointing at the wrong environment); corporate proxy blocking the request; auth service outage; the 'flow' client id being rejected after an API rename.

Related errors


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