Skip to content

Keep the OAuth identity as the first system block - #153

Merged
teamchong merged 2 commits into
mainfrom
fix/oauth-identity-first-system-block
Jul 26, 2026
Merged

Keep the OAuth identity as the first system block#153
teamchong merged 2 commits into
mainfrom
fix/oauth-identity-first-system-block

Conversation

@teamchong

@teamchong teamchong commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Fixes #149
Fixes #150

Problem

Every request through pxpipe fails with a 429 whose body says nothing:

{"type":"error","error":{"type":"rate_limit_error","message":"Error"},"request_id":"..."}

The account has quota left, and the same prompt succeeds without the proxy. The endpoint classifies a subscription-OAuth request as first-party only when the exact identity line is the first, separate top-level system block; an unclassified request is rejected as if rate-limited.

Cause

Compression rebuilds system, and the identity was landing too late. extractSystemText splits blocks on cache_control: once any text block carries a marker, every unmarked block is diverted to kept and re-emitted after the dynamic text. Claude Code marks only the big instruction block, so the unmarked identity block ended up behind # Environment.

Before:

[ { text: "# Environment\n..." },
  { text: "You are Claude Code, Anthropic's official CLI for Claude." } ]   // 429

After:

[ { text: "You are Claude Code, Anthropic's official CLI for Claude." },
  { text: "# Environment\n..." } ]                                          // 200

The identity is lifted out of kept before assembly, so it leads regardless of whether it arrived marked. The rest of the array keeps its existing order — # Environment stays last on purpose, since it churns every turn and would otherwise invalidate the cached prefix.

VS Code

The reporter saw this only in VS Code, with the terminal working. Claude Code 2.1.220 picks one of three identity lines by entrypoint, and only the first was recognized:

entrypoint identity line
terminal, Vertex You are Claude Code, Anthropic's official CLI for Claude.
claude -p, VS Code extension You are a Claude agent, built on Anthropic's Claude Agent SDK.
any of those + --append-system-prompt You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.

All three are matched now. The table is sorted longest-first because the third line has the first as a prefix, and the inline scan uses startsWith — shortest-first would emit a truncated identity and image the remainder.

Test

Reproduced against the live endpoint through pxpipe with the payload captured from the failing session: identity trailing or truncated -> 429 on every attempt; exact identity leading -> 200. pnpm typecheck and pnpm test (899 tests) pass.

The endpoint classifies a subscription-OAuth request as first-party only
when the exact identity line is the first, separate top-level system block.
When it is not, the request is answered with an opaque 429 rate_limit_error
carrying message "Error", even though the account has quota left (#149).

Compression rebuilds `system`, and it was putting the identity back too
late. extractSystemText splits blocks by cache_control: once any text block
carries a marker, every unmarked block is diverted to `kept` and re-emitted
after the dynamic text. The identity block is unmarked — Claude Code marks
only the big instruction block — so it landed behind `# Environment`.

Before:
  [ { text: "# Environment\n..." },
    { text: "You are Claude Code, Anthropic's official CLI for Claude." } ]

After:
  [ { text: "You are Claude Code, Anthropic's official CLI for Claude." },
    { text: "# Environment\n..." } ]

Also recognizes the Agent SDK identity, "You are a Claude agent, built on
Anthropic's Claude Agent SDK.", which the sdk-cli entrypoint sends instead:
`claude -p` and the VS Code extension. That is why the reporter saw this
fail in VS Code while the terminal kept working.
Claude Code 2.1.220 picks one of three identity lines, not two:

  if (vertex) return CLI;
  if (nonInteractive) return appendSystemPrompt ? CLI_WITHIN_SDK : AGENT_SDK;
  return CLI;

`--append-system-prompt` (any entrypoint) sends "You are Claude Code,
Anthropic's official CLI for Claude, running within the Claude Agent SDK.",
which was unrecognized and got imaged like ordinary text -> 429.

That line has the plain CLI line as a prefix, so the inline `startsWith`
scan would match the short one and emit a truncated identity:

  Before:
  { text: "You are Claude Code, Anthropic's official CLI for Claude." }
  <image: ", running within the Claude Agent SDK.\n\n# Environment...">

  After:
  { text: "You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK." }
  <image: "# Environment...">

Sorting the table longest-first makes the scan pick the exact line.
@teamchong
teamchong merged commit fa86400 into main Jul 26, 2026
6 checks passed
@teamchong
teamchong deleted the fix/oauth-identity-first-system-block branch July 26, 2026 19:18
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.

Compressed Claude Code Agent SDK requests get deterministic OAuth 429 in Desktop/stream-json mode Добавить работу с OPUS 5

1 participant