Skip to content

fix(claude-sdk-oauth): surface SDK error text and classify is_error results - #1312

Merged
code-yeongyu merged 11 commits into
mainfrom
fix/claude-sdk-oauth-error-surfacing
Sep 3, 2026
Merged

fix(claude-sdk-oauth): surface SDK error text and classify is_error results#1312
code-yeongyu merged 11 commits into
mainfrom
fix/claude-sdk-oauth-error-surfacing

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Claude SDK OAuth failures now preserve the SDK's real assistant/result text, including API and version-floor errors. Results marked is_error: true are failures even when their subtype is success, enabling fallback and multi-account failover for session limits and API errors. Token-refresh transport outages are classified as transient server errors rather than permanent auth blocks.

Changes

  • Centralized assistant/result failure extraction with HTTP and terminal-reason context.
  • Applied failure handling consistently to ambient streams, managed failover, resident session pumps, and turn-success bookkeeping.
  • Added transport/auth classification and actionable version-floor/model-not-found guidance.
  • Added regression and edge coverage using real Claude SDK wire shapes.

QA & Evidence

  • RED targeted tests failed for assertions before implementation: /Users/yeongyu/sisyphuslabs/.omo/evidence/ulw/claude-sdk-fable51-20260903/g2-red.log.
  • GREEN targeted tests passed: /Users/yeongyu/sisyphuslabs/.omo/evidence/ulw/claude-sdk-fable51-20260903/g2-green.log.
  • Three source mutations each failed their targeted tests: /Users/yeongyu/sisyphuslabs/.omo/evidence/ulw/claude-sdk-fable51-20260903/g2-mutation.log.
  • Edge behavior passed: /Users/yeongyu/sisyphuslabs/.omo/evidence/ulw/claude-sdk-fable51-20260903/g2-edge.log.
  • Remote typecheck and OAuth regression suite passed (66 files, 464 tests, 3 skipped): /Users/yeongyu/sisyphuslabs/.omo/evidence/ulw/claude-sdk-fable51-20260903/g2-regression.log.

Risks & Residuals

The full suite exercises scripted SDK wire shapes; live provider behavior remains dependent on Claude Code SDK message compatibility. No changes were made outside the scoped OAuth lane.

Related Issues

Fixes #1169
References #1298
References oh-my-openagent#7626

Credit @Altairpaca PR #1223 for the is_error result design and @eddieparc PR #1196 for transient refresh classification; both were superseded here.


Summary by cubic

Fixes Claude SDK OAuth error handling so real failure text surfaces and is_error results trigger failover instead of being treated as successes (fixes #1169, references #1298).

Bug Fixes

  • Assistant errors now surface the SDK's actual API text instead of unknown.
  • is_error results count as failures even with a success subtype; those that arrive before the replay claim surface as the API failure instead of a non-retryable attribution error, and their usage tokens are still recorded across the ambient, managed, and resident lanes.
  • Token-refresh transport outages are classified as transient server errors instead of permanent auth blocks.
  • Version-floor guidance names the required Claude Code version, and model-not-found errors include actionable upgrade guidance.

Written for commit 9a56914. Summary will update on new commits.

Review in cubic

code-yeongyu and others added 11 commits September 3, 2026 13:09
…esults

Ultraworked with [omo](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Ultraworked with [omo](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Ultraworked with [omo](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
Ultraworked with [omo](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: sisyphus-dev-ai <sisyphus-dev-ai@users.noreply.github.com>
…loor guidance

The version-floor hint interpolated a literal <version> placeholder. Parse the
required version out of the API error text ("version 2.1.251 or newer is
required") and name it in the CLAUDE_CODE_EXECUTABLE guidance; the #1298
regression now pins the interpolated version.
A claimed resident turn that receives a result with is_error true must reject
with the API text plus HTTP status/terminal reason and close the session; an
ordinary success result still settles on the idle-synced path.
…eplay claim

A result that fails before the SDK echoes the submitted user message (a 400
version floor, a 429 session limit) used to be reported as the attribution
error "result arrived before replay claim", which classifies as a
non-retryable other and hides the API text; failover therefore never rotated.
Classify the result first and reserve the attribution error for a genuine
success-before-claim.
Failing an is_error result before the success branch dropped the tokens the SDK
reported for it; record the usage before throwing.
The managed lane classifies an is_error result inside runFailover and the
resident pump rejects the turn before the result reaches the stream loop, so
accounting for usage only in that loop left both lanes at zero tokens. A failed
result now travels as SdkResultFailure carrying the SDK usage, and the stream's
error boundary accounts for it whether the failure arrived directly or wrapped
in a ClassifiedSdkError.
@code-yeongyu
code-yeongyu force-pushed the fix/claude-sdk-oauth-error-surfacing branch from b83209d to 9a56914 Compare September 3, 2026 04:09
@code-yeongyu
code-yeongyu merged commit 221e640 into main Sep 3, 2026
21 checks passed
@code-yeongyu
code-yeongyu deleted the fix/claude-sdk-oauth-error-surfacing branch September 3, 2026 04:17
code-yeongyu added a commit to code-yeongyu/oh-my-openagent that referenced this pull request Sep 3, 2026
The version-scoped bun patch and the omo-ai postinstall transform both
rewrote senpi's claude-sdk-oauth session-registry-pump so a result that
arrived before the replay claim surfaced its SDK cause instead of a bare
attribution error. senpi 2026.9.3-2 ships that upstream (code-yeongyu/senpi#1312:
the pump throws sdkResultFailure(message) ?? SessionTurnAttributionError),
so the old anchor line no longer exists and re-applying the transform made
postinstall fail with "unsupported Senpi" - which is what reddened the packed
install test and the result-before-replay pin on this PR.

Keep only the Claude Code version floor in senpi-patch.mjs, drop the bun
patch + patchedDependencies entry, and point the tests at the native
behavior: the installed pump carries sdkResultFailure, and a pre-replay
failure still classifies as query_failed through sanitizeTerminalFailure.
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.

Claude SDK ambient 429 result with success subtype bypasses model fallback

1 participant