zeroclaw-labs/zeroclaw · error · anyhow::Error
OpenAI device-code start failed ({status}): {body}
Error message
OpenAI device-code start failed ({status}): {body} What it means
start_device_code_flow POSTs to OpenAI's device authorization endpoint; the request itself completed (transport ok, hence no 'Failed to start' context error) but the HTTP status was non-2xx. The message embeds both the status code and the raw response body, which usually names the real cause (invalid client_id, blocked origin, or an upstream outage page).
Source
Thrown at crates/zeroclaw-providers/src/auth/openai_oauth.rs:147
}
pub async fn start_device_code_flow(client: &Client) -> Result<DeviceCodeStart> {
let form = [
("client_id", OPENAI_OAUTH_CLIENT_ID),
("scope", "openid profile email offline_access"),
];
let response = client
.post(OPENAI_OAUTH_DEVICE_CODE_URL)
.form(&form)
.send()
.await
.context("Failed to start OpenAI OAuth device-code flow")?;
if !response.status().is_success() {
let status = response.status();
let body = response.text().await.unwrap_or_default();
anyhow::bail!("OpenAI device-code start failed ({status}): {body}");
}
let parsed: DeviceCodeResponse = response
.json()
.await
.context("Failed to parse OpenAI device-code response")?;
Ok(DeviceCodeStart {
device_code: parsed.device_code,
user_code: parsed.user_code,
verification_uri: parsed.verification_uri,
verification_uri_complete: parsed.verification_uri_complete,
expires_in: parsed.expires_in,
interval: parsed.interval.unwrap_or(5).max(1),
message: parsed.message,
})
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the embedded body: 'invalid client' means the client_id/secret pair is wrong — check how alias_creds resolves credentials for the profile
- If the body is proxy/HTML noise, fix egress (proxy, TLS inspection) and retry
- Check https://status.openai.com for device-flow endpoint incidents and retry after recovery
- Fall back to the browser loopback flow (omit --device-code) if device authorization is blocked in your environment
Defensive patterns
Strategy: retry
Try / catch
let resp = openai_oauth::start_device_code_flow(&client, &id, &secret, &scopes).await;
match resp {
Err(e) => {
let msg = e.to_string();
if msg.contains("(400)") || msg.contains("(401)") {
return Err(e.context("device-flow credentials rejected — check client_id/secret")); // permanent
}
tokio::time::sleep(Duration::from_secs(5)).await; // 5xx/proxy: retry
}
ok => return ok,
} Prevention
- Verify client credentials resolve correctly (alias_creds) before starting device flow
- Watch for proxy HTML in the embedded body — it distinguishes egress issues from real OAuth errors
- Fall back to the loopback browser flow when device endpoints are blocked
When it happens
Trigger: `zeroclaw auth login --model-provider openai-codex --device-code` (or automatic fallback to device flow) when the endpoint returns e.g. 400 invalid_client, 401 bad credentials, or 5xx during an OpenAI incident.
Common situations: Client credentials mismatch after an app rotation, corporate proxies returning HTML error pages (so the body shows markup instead of JSON), or OpenAI auth endpoint outages.
Related errors
- OpenAI device-code polling failed ({status}): {text}
- OpenAI device-code polling failed ({status}): {}
- Device-code flow timed out before authorization completed
- OpenAI device-code authorization was denied
- OpenAI device-code expired
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/15ad24e4dd58bf02.
Report an issue: GitHub.