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

  1. Read the embedded body: 'invalid client' means the client_id/secret pair is wrong — check how alias_creds resolves credentials for the profile
  2. If the body is proxy/HTML noise, fix egress (proxy, TLS inspection) and retry
  3. Check https://status.openai.com for device-flow endpoint incidents and retry after recovery
  4. 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

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


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/15ad24e4dd58bf02. Report an issue: GitHub.