Kuberwastaken/claurst · error

Failed to exchange code

Error message

Failed to exchange code: {}

What it means

Wraps a reqwest transport failure that occurred while POSTing the OAuth authorization code (plus code_verifier and redirect_uri) to OpenAI's Codex token endpoint. The library uses anyhow to append the underlying reqwest error to the message. It means the HTTP request itself never completed, so no token status code was ever received.

Solutions

  1. Check basic network connectivity (curl https://auth.openai.com) and any HTTP(S)_PROXY environment variables.
  2. Retry the OAuth login flow; transient network failures resolve on retry.
  3. If behind a corporate proxy, configure reqwest-compatible proxy env vars or add the corporate CA to the trust store.
  4. If it persists, verify the CODEX_TOKEN_URL host is not blocked/renamed by your DNS provider.

Example fix

// before
let resp = client.post(CODEX_TOKEN_URL).form(&params).send().await.map_err(|e| anyhow!("Failed to exchange code: {}", e))?;
// after
let resp = client.post(CODEX_TOKEN_URL)
    .form(&params)
    .timeout(Duration::from_secs(30))
    .send()
    .await
    .map_err(|e| anyhow!("Failed to exchange code: {}", e))?;
Defensive patterns

Strategy: retry

Try / catch

// retry with backoff on transport failure
for attempt in 0..3 {
    match client.post(CODEX_TOKEN_URL).form(&params).send().await {
        Ok(resp) => break resp,
        Err(e) if attempt < 2 => tokio::time::sleep(Duration::from_secs(2u64 << attempt)).await,
        Err(e) => return Err(anyhow!("Failed to exchange code: {}", e)),
    }
}

Prevention

When it happens

Trigger: In exchange_code_for_tokens, client.post(CODEX_TOKEN_URL).form(&params).send() returns Err: DNS failure, connection refused/reset, TLS error, or request timeout while contacting the token URL during run_oauth_flow_with_label.

Common situations: No network access or offline machine; corporate proxy or firewall blocking the token endpoint; DNS misconfiguration; TLS interception with untrusted CA; transient server outage of the OAuth provider.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/282b20d49bf027cc. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/cli/src/codex_oauth_flow.rs:200

}

/// Exchange authorization code for access tokens.
async fn exchange_code_for_tokens(code: &str, verifier: &str) -> anyhow::Result<CodexTokens> {
    let client = reqwest::Client::new();
    let params = [
        ("client_id", CODEX_CLIENT_ID),
        ("code", code),
        ("code_verifier", verifier),
        ("grant_type", "authorization_code"),
        ("redirect_uri", CODEX_REDIRECT_URI),
    ];

    let resp = client
        .post(CODEX_TOKEN_URL)
        .form(&params)
        .send()
        .await
        .map_err(|e| anyhow!("Failed to exchange code: {}", e))?;

    if !resp.status().is_success() {
        let status = resp.status();
        let body = resp.text().await.unwrap_or_default();
        bail!("Token exchange failed ({}): {}", status, body);
    }

    let body: serde_json::Value = resp
        .json()
        .await
        .map_err(|e| anyhow!("Failed to parse token response: {}", e))?;

    let access_token = body["access_token"]
        .as_str()
        .unwrap_or("")
        .to_string();

    if access_token.is_empty() {

View on GitHub (pinned to b0637c97ec)