Raised on behalf of Chad J.
Bug Description
When openai-codex requests fail with a 403 HTTP response (HTML body), OpenClaw displays one of several misleading user-facing errors instead of correctly reporting a 403 auth failure. The raw response is visible in logs as rawErrorPreview but the user-facing message is wrong.
Critically: rawErrorPreview always contains an HTTP 403 HTML response, proving the endpoint was reached and responded. This definitively rules out DNS failure — yet users are told "DNS lookup failed."
Environment
- OpenClaw: 2026.4.9
- Provider: openai-codex
- Auth: ChatGPT OAuth (expires in 9d per status check)
- Models: gpt-5.4 and gpt-5.3-codex
- Endpoint configured: https://chatgpt.com/backend-api/codex
Observed Evidence
All three entries below are from the same run, same session, same ChatGPT endpoint — yet showing completely different user-facing errors despite identical rawErrorPreview:
Case 1 — "DNS lookup failed"
timestamp: 2026-04-10T05:04:38.436Z
user-facing error: "LLM request failed: DNS lookup for the provider endpoint failed."
rawErrorPreview: "403 <html>\\n <head>\\n <meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1\\" />\\n <style global>body{font-family:Arial,Helvetica,sans-serif}.container{align-items:center;display:flex..."
failoverReason: "auth"
status: (not present in this entry)
Case 2 — "API rate limit reached"
timestamp: 2026-04-10T05:05:53.844Z
user-facing error: "⚠️ API rate limit reached. Please try again later."
rawErrorPreview: "403 <html>\\n <head>\\n <meta name=\\"viewport\\" content=\\"width=device-width, initial-scale=1\\" />\\n <style global>body{font-family:Arial,Helvetica,sans-serif}.container{align-items:center;display:flex..."
failoverReason: "auth"
status: (not present in this entry)
Case 3 — raw 403 HTML shown
timestamp: 2026-04-10T05:04:59.634Z
user-facing error: "403 <html>\\n <head>..."
rawErrorPreview: same 403 HTML as above
failoverReason: "auth"
Case 4 — gpt-5.4 variant
timestamp: 2026-04-10T04:28:49.596Z
Embedded agent failed: "All models failed (2): openai-codex/gpt-5.4: LLM request failed: DNS lookup for the provider endpoint failed. (auth) | openai-codex/gpt-5.3-codex: LLM request failed: DNS lookup for the provider endpoint failed. (auth)"
failoverReason: "auth"
Sanitized Raw Snippet
The recurring rawErrorPreview:
403 <html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style global>body{font-family:Arial,Helvetica,sans-serif}.container{align-items:center;display:flex;flex-direction:column;gap:2rem;height:100%;justify-content:center;width:100%}@keyframes enlarge-appear{0%{opacity:0;transform:scale(75%) rotate(-90deg)}to{opacity:1;transform:scale(100%) rotate(0deg)}…
This is a ChatGPT login/access page (CSS classes .container, .scale-appear, .logo visible). Possible challenge/login HTML response.
Key Distinction: This Was NOT DNS
The rawErrorPreview contains an HTTP 403 response body — an HTML page. A true DNS failure produces no HTTP response at all. The fact that rawErrorPreview contains a 403 HTML body means:
- DNS resolution succeeded
- A TCP connection was established
- TLS handshake succeeded
- An HTTP response was received (403 status)
- The response body was an HTML login/challenge page
Failure Classification
| Actual Condition |
Correct User Message |
Observed User Messages |
| True DNS/network failure |
"Cannot reach provider" |
— |
| HTTP 403 auth/session invalid |
"ChatGPT session invalid — please re-authenticate" |
"DNS lookup failed" (wrong), "API rate limit reached" (wrong) |
| HTTP 429 rate limit |
"Rate limited — try again later" |
"API rate limit reached" (sometimes correct) |
| Possible Cloudflare/challenge HTML |
"Access challenge — try again" |
(mixed with auth failures above) |
Expected Behavior
- Classify errors from the actual HTTP status/body first
- Surface DNS failure only when no HTTP response was received
- When rawErrorPreview contains HTML (login page, challenge), show the appropriate auth-related message
- Rate-limit errors should be shown when HTTP 429 is actually returned, not from a 403 HTML body
Actual Impact
Users are sent down the wrong debugging path for hours:
- Checking DNS configuration
- Toggling VPN/Tailscale
- Reconfiguring network settings
- Verifying firewall rules
The real issue was an invalid OAuth session. Users cannot self-diagnose because the error message does not reflect the actual failure.
Relevant Existing Issues
Raised on behalf of Chad J.
Bug Description
When openai-codex requests fail with a 403 HTTP response (HTML body), OpenClaw displays one of several misleading user-facing errors instead of correctly reporting a 403 auth failure. The raw response is visible in logs as rawErrorPreview but the user-facing message is wrong.
Critically: rawErrorPreview always contains an HTTP 403 HTML response, proving the endpoint was reached and responded. This definitively rules out DNS failure — yet users are told "DNS lookup failed."
Environment
Observed Evidence
All three entries below are from the same run, same session, same ChatGPT endpoint — yet showing completely different user-facing errors despite identical rawErrorPreview:
Case 1 — "DNS lookup failed"
Case 2 — "API rate limit reached"
Case 3 — raw 403 HTML shown
Case 4 — gpt-5.4 variant
Sanitized Raw Snippet
The recurring rawErrorPreview:
This is a ChatGPT login/access page (CSS classes .container, .scale-appear, .logo visible). Possible challenge/login HTML response.
Key Distinction: This Was NOT DNS
The rawErrorPreview contains an HTTP 403 response body — an HTML page. A true DNS failure produces no HTTP response at all. The fact that rawErrorPreview contains a 403 HTML body means:
Failure Classification
Expected Behavior
Actual Impact
Users are sent down the wrong debugging path for hours:
The real issue was an invalid OAuth session. Users cannot self-diagnose because the error message does not reflect the actual failure.
Relevant Existing Issues