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
- Check the HTTP status in the message (404 → wrong URL/path, 401/403 → client blocked, 429 → rate limited, 5xx → server side)
- Verify the configured API base URL is correct for your environment (env var / config)
- Retry later if it's a 5xx/429 (server outage or rate limit)
- 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
- Verify the API base URL/environment before login
- Handle 429/5xx with retry + backoff instead of immediate bail
- Log the response body for server-side error detail
- Check proxy/VPN interference if failures are environment-specific
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
- device auth poll failed: HTTP {}
- device code expired. Run `f auth` again.
- Maple MCP request failed ({}): {}
- remote review failed: HTTP {}
- hub returned error: {}
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/8c92bdde785b6536.
Report an issue: GitHub.