claude-code - 💡(How to fix) Fix [Bug] Claude Desktop fullscreen "Claude will return soon" fallback caused by React TypeError: e.replace is not a function (errorCode 1GY780K) when rendering numeric MCP tool-result fields [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52320Fetched 2026-04-24 06:10:18
View on GitHub
Comments
2
Participants
3
Timeline
4
Reactions
0
Author
Timeline (top)
commented ×2labeled ×1subscribed ×1

Error Message

  • Renderer bundle at the time of filing: index-2Bphe_Ab.js (vendor vendor-P0aQfEyr.js). Error has recurred across at least 11 distinct frontend bundle hashes in my local claude.ai-web.log, so it has The [BOOTSTRAP] Fatal error boundary catches it and renders the fullscreen "Claude will return soon. Claude is currently experiencing a temporary service disruption. We're working on it, check back soon" screen with a non-functional "Try again" button. The error-boundary text is misleading — there is no service disruption; this is a client-side unhandled exception. [error] [BOOTSTRAP] Fatal error boundary triggered
  1. The error-boundary UX: the "Try again" button currently re-mounts the same broken subtree and so loops forever. The fallback should at minimum allow the user to navigate away from (or delete) the /api/organizations/<org>/chat_conversations/<uuid>/tool_result returning HTTP 404 from the claude.ai backend. Visible in the same renderer log as QueryClient error:

Root Cause

Probable root cause:
.replace() is being called on a value that is a JSON number rather than a string. The frame order suggests a useMemo that formats a tool-result field — likely stripping trailing zeros or formatting a display value — without first checking/coercing the type. Example MCP tool response that triggers it:

RAW_BUFFERClick to expand / collapse

Severity: High — poisons any conversation whose history contains the triggering tool result. The fullscreen fallback's "Try again" button re-mounts the same crashing component, so it loops. Only recovery is Cmd+Q and relaunch; reopening the poisoned chat re-triggers it immediately.

Environment:

  • Claude Desktop 1.3883.0 (macOS, Darwin 25.4.0)
  • Renderer bundle at the time of filing: index-2Bphe_Ab.js (vendor vendor-P0aQfEyr.js). Error has recurred across at least 11 distinct frontend bundle hashes in my local claude.ai-web.log, so it has survived multiple deploys.
  • MCP server: third-party local stdio server that returns JSON numbers in tool-result fields. The bug is reproducible with any MCP server whose tool-result JSON contains a numeric field.

Symptom:
When an MCP tool returns a response containing numeric fields (e.g. a float like 0.2800000011920929), the claude.ai web app renderer throws TypeError: e.replace is not a function inside a useMemo.
The [BOOTSTRAP] Fatal error boundary catches it and renders the fullscreen "Claude will return soon. Claude is currently experiencing a temporary service disruption. We're working on it, check back
soon" screen with a non-functional "Try again" button. The error-boundary text is misleading — there is no service disruption; this is a client-side unhandled exception.

Closing and reopening Claude Desktop recovers, but reopening the affected conversation re-renders the same message history and crashes again instantly. New chats stay clean until an MCP tool call
produces the same response shape, at which point that chat also becomes permanently poisoned.

Evidence from ~/Library/Logs/Claude/claude.ai-web.log (most recent entry, 2026-04-23 09:51:26):

[error] [BOOTSTRAP] Fatal error boundary triggered
{
"errorMessage": "e.replace is not a function", "errorCode": "1GY780K",
"url": "/chat/a9268f10-b41a-42b1-af14-969237a65738",
"errorStack": "TypeError: e.replace is not a function
at Jtt (https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/index-2Bphe_Ab.js:21:551191) at rnt (.../index-2Bphe_Ab.js:21:553532)
at Upt (.../index-2Bphe_Ab.js:23:404506)
at Kpt (.../index-2Bphe_Ab.js:23:409463)
at .../index-2Bphe_Ab.js:23:596125
at Object.Xi [as useMemo] (.../vendor-P0aQfEyr.js:11:61312)
at Ea.ka.useMemo (.../vendor-P0aQfEyr.js:2:68085)
..."
}

Probable root cause:
.replace() is being called on a value that is a JSON number rather than a string. The frame order suggests a useMemo that formats a tool-result field — likely stripping trailing zeros or formatting a display value — without first checking/coercing the type. Example MCP tool response that triggers it:

{
"name": "Engine B Delay",
"value": 0.11999999731779099, "normalized_value": 0.12,
"display_value": "2.07 ms",
"is_quantized": false,
"clamped": false
}

value and normalized_value are JSON numbers. The MCP spec does not require tool-result fields to be strings, so the frontend assumption is a bug.

Reproduction:

  1. Configure any local stdio MCP server in Claude Desktop that returns at least one numeric field in a tool-call result (a minimal tool returning {"value": 0.28, "normalized_value": 0.28, "display_value": "28 %"} suffices).
  2. Invoke that tool from a Claude Desktop chat.
  3. The fullscreen "Claude will return soon" fallback appears within ~1 second of the tool response being rendered.
  4. Reopening the same conversation re-triggers the fallback on every mount.

Suggested fix (two separate):

  1. The actual bug: wherever the crashing useMemo coerces a tool-result field, guard the .replace() call — either String(v).replace(...) or typeof v === "string" ? v.replace(...) : v. Same guard
    should apply to any other string method called on tool-result fields.
  2. The error-boundary UX: the "Try again" button currently re-mounts the same broken subtree and so loops forever. The fallback should at minimum allow the user to navigate away from (or delete) the poisoned chat without relaunching the app. The displayed text should not say "service disruption" for client-side render errors — that misleads users into waiting for an outage that isn't happening.

Related bug, same app (file as a separate issue or note in the same report — your call): The yellow "Tool result could not be submitted. The request may have expired or the connection was interrupted. Refresh the page to continue." popup is caused by POST
/api/organizations/<org>/chat_conversations/<uuid>/tool_result returning HTTP 404 from the claude.ai backend. Visible in the same renderer log as QueryClient error:
{"type":"not_found_error","statusCode":404,"endpoint":"/api/organizations/.../tool_result"}. The user-facing message misattributes this — it is not a timeout or connection drop, it is a 404 on the
submission endpoint.

extent analysis

TL;DR

The most likely fix is to guard the .replace() call in the useMemo hook by checking if the value is a string before calling the method.

Guidance

  • Identify the useMemo hook that formats the tool-result field and add a type check to ensure the value is a string before calling .replace().
  • Consider using String(v).replace(...) or typeof v === "string" ? v.replace(...) : v to guard the .replace() call.
  • Review the error-boundary UX to prevent the "Try again" button from re-mounting the same broken subtree and to display a more accurate error message.
  • Investigate the related bug causing the "Tool result could not be submitted" popup and update the user-facing message to reflect the actual error (404 on the submission endpoint).

Example

// Before
useMemo(() => {
  const formattedValue = value.replace(/\.0+$/, '');
  // ...
}, [value]);

// After
useMemo(() => {
  const formattedValue = typeof value === "string" ? value.replace(/\.0+$/, '') : value;
  // ...
}, [value]);

Notes

The fix assumes that the useMemo hook is the root cause of the issue. Additional debugging may be necessary to confirm this. The related bug causing the "Tool result could not be submitted" popup should be investigated and fixed separately.

Recommendation

Apply the workaround by guarding the .replace() call in the useMemo hook to prevent the TypeError and improve the error-boundary UX to provide a more accurate error message.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING