router-for-me/CLIProxyAPI · error
token exchange request failed: %w
Error message
token exchange request failed: %w
What it means
The HTTP round trip for the Codex token exchange (POST to TokenURL) failed at the transport level — DNS, TCP connect, TLS handshake, or mid-request disconnect. The request was built successfully; the error comes from httpClient.Do and is wrapped verbatim, so the underlying cause (dial tcp, x509, proxyconnect, etc.) is visible in the wrapped message.
Source
Thrown at internal/auth/codex/openai_auth.go:126
data := url.Values{
"grant_type": {"authorization_code"},
"client_id": {ClientID},
"code": {code},
"redirect_uri": {strings.TrimSpace(redirectURI)},
"code_verifier": {pkceCodes.CodeVerifier},
}
req, err := http.NewRequestWithContext(ctx, "POST", TokenURL, strings.NewReader(data.Encode()))
if err != nil {
return nil, fmt.Errorf("failed to create token request: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
resp, err := o.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("token exchange request failed: %w", err)
}
defer func() {
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read token response: %w", err)
}
// log.Debugf("Token response: %s", string(body))
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("token exchange failed with status %d: %s", resp.StatusCode, string(body))
}
// Parse token response
var tokenResp struct {
AccessToken string `json:"access_token"`View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the wrapped error text to identify the layer (DNS, TLS, proxy, reset) before changing anything.
- Test reachability: `curl -v <TokenURL>` from the same machine and user.
- If behind a TLS-intercepting proxy, trust its CA cert or set SSL_CERT_FILE/SSL_CERT_DIR.
- Fix or unset HTTP_PROXY/HTTPS_PROXY/NO_PROXY for the login process.
- Retry the login once network is confirmed working — transient resets are common.
Example fix
// before: default client, no proxy awareness
resp, err := o.httpClient.Do(req)
// after: ensure the client honors the environment and retries transport errors
transport := &http.Transport{ Proxy: http.ProxyFromEnvironment }
o.httpClient = &http.Client{ Transport: transport, Timeout: 30 * time.Second } Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: confirm the token endpoint resolves and is reachable
if _, err := net.DialTimeout("tcp", "auth.openai.com:443", 5*time.Second); err != nil {
return fmt.Errorf("token endpoint unreachable, fix network first: %w", err)
} Try / catch
tok, err := auth.ExchangeCode(ctx, code)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) || strings.Contains(err.Error(), "dial") || strings.Contains(err.Error(), "proxy") {
// transient transport failure: safe to restart the login flow later
log.Warnf("network error during exchange: %v", err)
}
return err
} Prevention
- Configure proxy env vars correctly before starting login.
- Trust corporate CA certs via SSL_CERT_FILE when behind TLS interception.
- Keep the login context deadline generous (minutes) to survive slow networks.
When it happens
Trigger: No internet or DNS failure resolving the OpenAI auth host; TLS interception by a corporate proxy with an untrusted CA; HTTP(S)_PROXY env var pointing at a dead proxy; connection reset by a firewall between the host and the token endpoint; context canceled while the request was in flight.
Common situations: Running login behind corporate proxy/VPN without configuring the proxy CA; egress firewall blocking the auth domain; flaky network during interactive login; HTTPS_PROXY misconfigured in the shell where cli-proxy-api runs.
Related errors
- antigravity token exchange: execute request: %w
- execute request: %w
- fetch Claude OAuth %s: %w
- claude oauth tls: dial upstream: %w
- failed to read token response: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/24aaf5ca0848cf66.
Report an issue: GitHub.