Skip to content

fix(openai-codex): use /backend-api/codex/ base URL#69336

Merged
steipete merged 1 commit intoopenclaw:mainfrom
mzogithub:fix/openai-codex-baseurl-2026-04-20
Apr 21, 2026
Merged

fix(openai-codex): use /backend-api/codex/ base URL#69336
steipete merged 1 commit intoopenclaw:mainfrom
mzogithub:fix/openai-codex-baseurl-2026-04-20

Conversation

@mzogithub
Copy link
Copy Markdown

TL;DR

OpenAI removed the /backend-api/responses alias on chatgpt.com server-side. The OpenAI SDK appends /responses to the configured baseUrl, so OpenClaw's current baseUrl (https://chatgpt.com/backend-api) now resolves to /backend-api/responses and hits a Cloudflare HTML 403 block page. OpenClaw's error classifier then surfaces this as an auth-scope failure, triggering fruitless OAuth re-login loops for every openai-codex/gpt-5.4 call.

This PR points the base URL at https://chatgpt.com/backend-api/codex so the SDK builds .../backend-api/codex/responses, which still returns 200 OK with normal SSE streaming.

Symptom

  • Every openai-codex/gpt-5.4 (and sibling gpt-5.4-pro / gpt-5.4-mini) call fails with:

    Authentication failed with an HTML 403 response from the provider. Re-authenticate…

  • Interactive OAuth re-login succeeds, token refreshes normally, but the next call fails the same way. Loops indefinitely.
  • LCM compaction against openai-codex/gpt-5.4 hits the same 403 and falls back to raw truncation.
  • Gateway logs show HTTP 403 + HTML body on POSTs to https://chatgpt.com/backend-api/responses.

Root cause (verified with live curl)

Using the exact OAuth access token OpenClaw persists in auth-profiles.json:

POST https://chatgpt.com/backend-api/responses          → HTTP 403 (HTML Cloudflare block page)
POST https://chatgpt.com/backend-api/codex/responses    → HTTP 200 (streams SSE normally)

Same Authorization: Bearer <token> header in both cases. Only the path differs. Cloudflare — not OpenAI auth — is gating the legacy alias. OpenAI apparently removed the /backend-api/responses alias some time in the last ~24 hours (2026-04-19/20 window); only /backend-api/codex/responses is live now.

The error then surfaces as "re-authenticate" because OpenClaw's provider-level HTML body + 403 classifier treats Cloudflare block pages as an auth-scope failure. The token is fine — the URL is wrong.

Fix

Three source changes:

  1. extensions/openai/openai-codex-catalog.ts — change OPENAI_CODEX_BASE_URL from "https://chatgpt.com/backend-api" to "https://chatgpt.com/backend-api/codex".

  2. extensions/openai/openai-codex-provider.ts — same change to the sibling local constant.

  3. extensions/openai/base-url.ts — extend isOpenAICodexBaseUrl so both the new canonical form AND the legacy form are recognized as a Codex baseURL. Backward compatibility matters here because user configs and persisted model metadata may still contain the legacy URL; the existing normalizeCodexTransport flow then round-trips them to the new canonical form.

    - return /^https?:\/\/chatgpt\.com\/backend-api(?:\/v1)?\/?$/i.test(trimmed);
    + return /^https?:\/\/chatgpt\.com\/backend-api(?:\/codex)?(?:\/v1)?\/?$/i.test(trimmed);

Backward compatibility

  • Existing user configs with baseUrl: "https://chatgpt.com/backend-api" are still recognized by isOpenAICodexBaseUrl, so they still route through the Codex transport and get normalized to the new canonical form by normalizeCodexTransport / normalizeResolvedModel on the next model resolution.
  • No persisted-config migration is required; users don't need to touch their openclaw.json.
  • openai-codex/gpt-5.4 requests start succeeding the moment the gateway picks up the new build.

Tests

Added positive-case coverage for the new base URL:

  • extensions/openai/base-url.test.ts
    • https://chatgpt.com/backend-api/codextrue
    • https://chatgpt.com/backend-api/codex/true
    • https://chatgpt.com/backend-api/codex/v1true
    • https://chatgpt.com/backend-api/codex/v1/true
    • Legacy forms still → true (backward compat).
    • https://chatgpt.com/backend-api/codex/v2false (new negative case).

Updated existing assertions whose expected canonical URL now includes /codex:

  • extensions/openai/openai-codex-provider.test.ts — three cases: normalizeResolvedModel default-api filling, normalizeResolvedModel stale /v1 → canonical, and normalizeTransport stale /v1 → canonical. The stale-/v1 migration tests continue to cover the same behavior; they now assert migration to the new canonical form.
  • extensions/openai/openai-provider.test.ts — one resolveDynamicModel fallback case (empty registry → uses the constant directly).

Tests that pass the legacy URL as input but assert on non-URL fields (tool schema normalization, transport-policy headers, etc.) were left alone — they exercise the backward-compat path and continue to pass.

Verification steps

pnpm tsgo
pnpm build
pnpm test extensions/openai/base-url.test.ts
pnpm test extensions/openai/openai-codex-provider.test.ts
pnpm test extensions/openai/transport-policy.test.ts

Local results against origin/main at 442deb0816:

  • pnpm tsgo — clean.
  • pnpm build — clean.
  • base-url.test.ts — 4/4 passing.
  • openai-codex-provider.test.ts — 16/16 passing.
  • transport-policy.test.ts — 5/5 passing.
  • openai-provider.test.ts (touched) — 25/25 passing.
  • index.test.ts (Codex tool-schema normalization, smoke) — passing.

Notes for reviewers

  • This is a hotfix: every OpenClaw deployment using openai-codex/gpt-5.4 is currently broken by the upstream Cloudflare block. Each deployment-owner is presumably burning through fruitless re-auth attempts until the baseUrl constant lands.
  • The isOpenAICodexBaseUrl regex intentionally keeps the legacy shape recognized. Once this has been out long enough that no persisted configs still carry https://chatgpt.com/backend-api, the legacy branch of the regex can be removed in a follow-up; the runtime normalizer already upgrades on the first round-trip.
  • Checklist items I can verify locally (tests, tsgo, build) are green; CI will cover the ones I can't.

OpenAI removed the /backend-api/responses alias on chatgpt.com server-side.
The OpenAI SDK appends /responses to the configured baseUrl, so OpenClaw's
current baseUrl ("https://chatgpt.com/backend-api") now resolves to
/backend-api/responses and hits a Cloudflare HTML 403 block page. The
provider's 403+HTML error classifier then surfaces this as an auth-scope
failure, triggering fruitless OAuth re-login loops for every GPT-5.4
sub-agent call.

- Point OPENAI_CODEX_BASE_URL at https://chatgpt.com/backend-api/codex
  (both the catalog constant and the sibling local constant in the provider).
- Extend isOpenAICodexBaseUrl to accept the new /codex segment while keeping
  the legacy path recognized so pre-existing user configs and persisted
  model metadata still round-trip through the normalizer correctly.
- Add positive-case test coverage for the new base URL; update existing
  normalization tests whose expected canonical output now includes /codex.

Verified with live curl using the exact OAuth access token stored by
OpenClaw: the /codex/responses path returns HTTP 200 with streaming SSE,
while the old /responses alias returns HTTP 403 HTML regardless of auth
headers. Scoped tests (base-url, openai-codex-provider, transport-policy,
openai-provider, index) pass; pnpm tsgo and pnpm build are clean.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This hotfix updates the OpenAI Codex base URL from https://chatgpt.com/backend-api to https://chatgpt.com/backend-api/codex after OpenAI removed the /backend-api/responses alias server-side, causing all openai-codex calls to hit a Cloudflare 403 block page. The regex in isOpenAICodexBaseUrl is extended to recognise both the new canonical form and the legacy form, so existing user configs continue to route through the Codex transport and are silently upgraded on the next round-trip via normalizeCodexTransport.

Confidence Score: 5/5

Safe to merge — targeted hotfix restoring a broken endpoint with full backward compatibility.

All three code changes are minimal and precise: two constant updates and one regex extension. The regex correctly handles all expected forms (new canonical, legacy, v1 variants, trailing slashes) and rejects non-matching paths. Backward-compat normalization via normalizeCodexTransport is already in place and unmodified. Test suite covers positive and negative cases for both URL shapes. No unrelated code is touched.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(openai-codex): use /backend-api/code..." | Re-trigger Greptile

@steipete steipete merged commit 8a2d7f2 into openclaw:main Apr 21, 2026
50 of 51 checks passed
@steipete
Copy link
Copy Markdown
Contributor

Landed via rebase onto main.

  • Gate: pnpm test extensions/openai/base-url.test.ts extensions/openai/openai-codex-provider.test.ts extensions/openai/openai-provider.test.ts extensions/openai/transport-policy.test.ts extensions/openai/index.test.ts; pnpm check:changed; direct OpenAI Responses live smoke with .profile OPENAI_API_KEY using gpt-5.4-nano returned OK.
  • Note: pnpm test:live -- extensions/openai/openai-provider.live.test.ts hung before test output, so I used the equivalent direct Responses smoke with a hard timeout for live verification.
  • Source commit: 2bb3635
  • Merge commit: 8a2d7f2

Thanks @mzogithub!

loongfay pushed a commit to YuanbaoTeam/openclaw that referenced this pull request Apr 21, 2026
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
zhonghe0615 pushed a commit to zhonghe0615/openclaw that referenced this pull request May 7, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants