Skip to content

fix(codex): drop user parameter — ChatGPT backend rejects it - #22

Open
cheapsteak wants to merge 1 commit into
AmazingAng:mainfrom
cheapsteak:fix/codex-drop-user-param
Open

fix(codex): drop user parameter — ChatGPT backend rejects it#22
cheapsteak wants to merge 1 commit into
AmazingAng:mainfrom
cheapsteak:fix/codex-drop-user-param

Conversation

@cheapsteak

Copy link
Copy Markdown

Symptom

When a request is routed through the codex provider (anthropicToResponsesRequest → ChatGPT /responses backend), the backend rejects any request that includes a top-level user field:

HTTP 400
{"detail":"Unsupported parameter: user"}

Claude Code (and presumably any Anthropic-protocol client that populates metadata.user_id, which is part of the public Anthropic Messages API) sends metadata.user_id on every /v1/messages request, so the codex provider is effectively unusable from Claude Code today — every turn fails.

Where

src/upstream/responses-translator.ts:313, inside anthropicToResponsesRequest:

if (body.metadata?.user_id) out.user = body.metadata.user_id;

The translator's only consumer is the codex path in src/handlers/anthropic.ts (proxyCodexMessages, gated on provider.id === "codex"), so the offending forward fires for every Anthropic-protocol request that targets a codex-served model.

Reproduction

With a configured codex account, from any Anthropic-protocol client (or curl):

curl -sS -X POST http://localhost:PORT/v1/messages \
  -H 'content-type: application/json' \
  -H 'x-api-key: ...' \
  -H 'anthropic-version: 2023-06-01' \
  -d '{
    "model": "<codex-served-model>",
    "max_tokens": 64,
    "metadata": {"user_id": "anyone"},
    "messages": [{"role":"user","content":"hi"}]
  }'

Upstream response body:

{"detail":"Unsupported parameter: user"}

Remove metadata.user_id from the same request and it succeeds.

Fix

Drop the unconditional metadata.user_iduser forward in anthropicToResponsesRequest. Since that translator is codex-only (the only call site is proxyCodexMessages), an unconditional removal is the simplest correct change; this PR takes that route and leaves an inline NOTE comment explaining the constraint so it isn't accidentally re-added.

If anthropicToResponsesRequest ever gains a non-codex consumer, the forward can be gated by provider id at the handler layer instead.

Likely related (not verified)

src/upstream/responses-translator.ts:184, inside chatToResponsesRequest:

if (body.user) out.user = body.user;

This is the Chat-Completions → Responses path. If that translator is ever routed to the codex backend with a client that sends a top-level user, the same 400 should occur. I have not reproduced this from Claude Code (Claude Code uses the Anthropic path), so I'm flagging it as a separate observation rather than fixing it here.

The ChatGPT Codex backend (consumed via the Anthropic → Responses
translator) rejects requests that include a top-level `user` field with:

    HTTP 400 {"detail":"Unsupported parameter: user"}

Claude Code (and any Anthropic-protocol client that populates
`metadata.user_id`) hits this on every request, making the codex
provider unusable from Claude Code.

Drop the `metadata.user_id` → `user` forward in
`anthropicToResponsesRequest`. A comment is left in its place so the
constraint isn't accidentally re-added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant