{"record":{"id":"a65c4264355724f7","repo":"unslothai/unsloth","slug":"chatgpt-codex-endpoint-returned-a-forbidden-redire","errorCode":null,"errorMessage":"ChatGPT Codex endpoint returned a forbidden redirect.","messagePattern":"ChatGPT Codex endpoint returned a forbidden redirect\\.","errorType":"exception","errorClass":"CodexTransportError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/inference/openai_codex_client.py","lineNumber":362,"sourceCode":"    for attempt in range(_MAX_TRANSIENT_RETRIES + 1):\n        yielded = False\n        try:\n            async with _stream_response(\n                client,\n                url = url,\n                headers = headers,\n                body = body,\n                cancel_event = cancel_event,\n            ) as response:\n                if response is None:\n                    yield None\n                    return\n                if 200 <= response.status_code < 300:\n                    yielded = True\n                    yield response\n                    return\n                if 300 <= response.status_code < 400:\n                    raise CodexTransportError(\n                        \"ChatGPT Codex endpoint returned a forbidden redirect.\"\n                    )\n                detail = await _upstream_error_detail(response)\n                if response.status_code == 401 and refresh_access is not None and not refreshed:\n                    try:\n                        token, account_id = await refresh_access()\n                    except CodexReauthorizationRequired as exc:\n                        raise CodexReauthorizationError(\n                            \"ChatGPT authorization expired. Reconnect this connection.\",\n                            status = 401,\n                            metadata = {\"access_token\": token},\n                        ) from exc\n                    except Exception as exc:\n                        raise CodexTransportError(\n                            \"Could not refresh ChatGPT authorization. Please retry.\",\n                            status = 502,\n                        ) from exc\n                    headers[\"Authorization\"] = f\"Bearer {token}\"","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/openai_codex_client.py#L344-L380","documentation":"The Codex backend HTTP client treats any 3xx redirect as a transport error because the ChatGPT Codex responses endpoint is not supposed to redirect. A redirect here usually means the request never reached the real API: an intercepting proxy, captive portal, wrong base URL, or region-block returned a redirect page instead of the endpoint.","triggerScenarios":"POST/GET to the Codex responses endpoint returns a status in 300..399 (httpx redirects are disabled or the redirect crosses methods). Typical with corporate SSL-inspection proxies, a misconfigured base URL pointing at a login page, or DNS hijacking.","commonSituations":"Corporate proxy that redirects API traffic to an auth page; HTTPS_PROXY/HTTP_PROXY env vars set to a proxy that blocks chatgpt.com; custom base URL configured to a domain that 302s; captive-portal WiFi; region where the endpoint is blocked.","solutions":["Check proxy configuration: bypass or correctly authenticate the proxy for the Codex endpoint domain","Verify the configured Codex base URL is the direct API endpoint, not a portal/login host","Reproduce with curl -v --max-redirs 0 against the endpoint to see where the redirect points","If on captive/filtered networks, connect from an unrestricted network to confirm"],"exampleFix":"# before\nexport HTTPS_PROXY=http://proxy.corp:3128  # proxy 302s API calls to a login page\n\n# after\nexport HTTPS_PROXY=http://proxy.corp:3128\nexport NO_PROXY=chatgpt.com,api.openai.com  # bypass proxy for the Codex endpoint","handlingStrategy":"validation","validationCode":"import socket, urllib.parse\nhost = urllib.parse.urlparse(CODEX_BASE_URL).hostname\nassert socket.gethostbyname(host), 'DNS fails for Codex endpoint'\n# smoke test: endpoint must not redirect\nimport httpx\nr = httpx.post(CODEX_BASE_URL, follow_redirects=False, timeout=5,\n               headers={'Authorization': 'Bearer x'})\nif 300 <= r.status_code < 400:\n    raise EnvironmentError('Proxy/network redirects Codex traffic — fix egress')","typeGuard":null,"tryCatchPattern":"try:\n    async for chunk in stream:\n        ...\nexcept CodexTransportError as exc:\n    if 'forbidden redirect' in str(exc):\n        run_network_diagnostics_and_warn_user()\n        return\n    raise","preventionTips":["Add the Codex endpoint domain to proxy bypass lists at deployment time","Run a redirect smoke test against the endpoint in startup health checks","Never point the base URL at a portal/login host; validate it resolves to the API"],"tags":["network","proxy","codex","http"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}