Skip to content

fix(chat): unwrap raw JSON provider error payloads into readable messages#3830

Open
xxashxx-svg wants to merge 1 commit into
pingdotgg:mainfrom
xxashxx-svg:fix/provider-error-raw-json
Open

fix(chat): unwrap raw JSON provider error payloads into readable messages#3830
xxashxx-svg wants to merge 1 commit into
pingdotgg:mainfrom
xxashxx-svg:fix/provider-error-raw-json

Conversation

@xxashxx-svg

@xxashxx-svg xxashxx-svg commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Fixes #3747

What

Model/provider errors were rendered in the chat UI as the raw upstream JSON body, e.g.

{"type":"error","status":400,"error":{"type":"invalid_request_error","message":"The 'gpt-5.3-codex' model is not supported when using Codex with a ChatGPT account."}}

and since that string is one long unbreakable token, it also overflowed/clipped the error banner.

Why it happens

Codex fills the error.message / turn.error.message notification fields with the stringified upstream response body, and t3code passes that string through verbatim into session.lastError and runtime.error events. ThreadErrorBanner then renders it as-is with line-clamp-3 but no word-breaking, so the unwrappable token can't clamp and overflows instead.

Changes

  • packages/shared/providerError.ts (new): extractProviderErrorMessage() — if an error string parses as JSON with a message (or nested error.message) field, return that; otherwise return the input unchanged. Handles double-encoded payloads. Shared module per the maintainability guidance in AGENTS.md, since both server and web need it. 8 unit tests included.
  • apps/server (CodexSessionRuntime, CodexAdapter): apply it at the four places codex error text becomes session.lastError / turn.completed.errorMessage / runtime.error.message.
  • apps/web (ThreadErrorBanner): unwrap defensively too (covers lastError values persisted before this fix, and any other adapter with the same habit), and add break-words to the banner + tooltip so a long unbreakable string wraps and clamps properly instead of clipping.

Raw payload details are unaffected for debugging — the runtime.error event still carries the original payload in detail.

Before / after

With the payload above, the banner previously showed the full raw JSON (clipped); it now shows:

The 'gpt-5.3-codex' model is not supported when using Codex with a ChatGPT account.

Checks

  • vp check
  • vp run typecheck ✅ (all 15 packages)
  • packages/shared + codex adapter/runtime test suites pass; the only failures in packages/shared (logging.test.ts, relayClient.test.ts) also fail on a clean checkout of main on this machine (Windows env-specific) and are untouched by this PR.

🤖 Generated with Claude Code


Note

Low Risk
Localized display and message normalization for Codex errors; no auth or persistence schema changes, and debugging payloads remain in event detail.

Overview
Codex often forwards stringified upstream error JSON as the user-visible message, which showed up as one long token in the chat error banner and overflowed line-clamp-3.

This PR adds extractProviderErrorMessage in @t3tools/shared/providerError (with unit tests) to pull a human-readable message or nested error.message from JSON-shaped strings, including double-encoded payloads, and leaves plain text unchanged.

Server: Codex CodexAdapter and CodexSessionRuntime apply the helper when setting turn.completed.errorMessage, runtime.error / warning messages, and session.lastError from turn failures and provider error notifications. runtime.error still keeps the raw payload in detail.

Web: ThreadErrorBanner unwraps errors again for values stored before the server change, and adds break-words on the banner and tooltip so long strings wrap and clamp correctly.

Reviewed by Cursor Bugbot for commit 8d8118e. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Unwrap raw JSON provider error payloads into readable messages in chat

  • Adds extractProviderErrorMessage in providerError.ts that parses JSON error bodies from providers, extracts a human-readable message string, and recursively unwraps double-encoded payloads, returning the original input unchanged for non-JSON or unrecognized formats.
  • Applies extractProviderErrorMessage in CodexAdapter.ts and CodexSessionRuntime.ts so turn/completed and error runtime events carry unwrapped messages.
  • Updates ThreadErrorBanner.tsx to unwrap previously persisted raw JSON errors at render time and adds break-words to prevent long-token overflow.

Macroscope summarized 8d8118e.

…ages

Codex surfaces upstream error bodies verbatim as the error message string,
so the chat error banner rendered raw JSON like
{"type":"error","status":400,"error":{...}} and the unbroken token
overflowed its container.

- add extractProviderErrorMessage to @t3tools/shared that pulls the nested
  human-readable message out of JSON-shaped error strings (no-op otherwise)
- apply it where codex errors become session.lastError / runtime.error
- unwrap defensively in ThreadErrorBanner for already-persisted errors and
  add break-words so long unbreakable strings wrap instead of clipping

Fixes pingdotgg#3747

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 89adb803-cd1b-4858-8c3e-b4cdad2ef77f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 9, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved

This PR adds a defensive utility to extract readable messages from JSON error payloads, improving error message UX. The changes are self-contained, well-tested, and don't alter when errors occur or error handling behavior - only how messages are displayed.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Model error messages render as broken raw JSON in the UI

2 participants