CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-05-24Intermediate

Recovering from Claude Code's 'Tool result could not be submitted'

What 'Tool result could not be submitted' really means in Claude Code, and the practical recovery steps I rely on after years of running indie apps with 50M+ downloads through it.

Claude Code196ErrorsTool Use8MCP45Troubleshooting11

You are halfway through a long Bash run or waiting on a slow MCP server, and the terminal suddenly prints a flat red line: Tool result could not be submitted. If you use Claude Code daily, you have probably seen it at least once. As an indie developer who has run an app business with over 50 million downloads through Claude Code, I have watched this exact failure swallow entire afternoons, especially in periods when I was adding new MCP servers every other day.

The message is short and the temptation is to mash /cancel or close the terminal. Both of those reactions tend to make things worse. Let me walk you through the failure mode the way I actually think about it on a Tuesday afternoon.

When this error shows up

The error fires when Claude Code finishes a tool call (Bash, Read, Edit, an MCP tool, or your own custom MCP) but cannot deliver the result back to Claude. From my own logs, the common triggers are:

  • An MCP server returning an unexpectedly large JSON payload (hundreds of KB up to a few MB) in a single response
  • A casual Bash call like grep -r or find whose output balloons to tens of thousands of lines
  • Your network blinking out mid-stream, even for a second, while the result is being sent
  • A /cancel press followed too quickly by a new prompt

In every case, the tool itself did its job. What failed is the layer that hands the result back to Claude. That distinction matters when you decide how to recover.

Surface cause vs real cause

The instinct is to blame the tool or the MCP server. After years of debugging, I have learned that the real culprits are almost always one of three things:

  1. Result payload size. Claude Code enforces a practical ceiling on the size of a single ToolResult. Cross it and the message is dropped silently with this error.
  2. ToolUseId / ToolResultId mismatch. If you cancel one call and immediately start another, the pending ToolResult can end up orphaned, and the next call gets rejected.
  3. Streaming disconnects. A momentary VPN flap or Wi-Fi roam is enough for the client to give up on the result.

Treat the error as a delivery problem, not a tool problem. That mental model alone fixes 80% of the panic.

Immediate recovery, without burning your session

When the error appears, the goal is to preserve as much of your hard-earned context as possible. Here is the order I follow:

  1. Press Enter once with no extra input. Occasionally the client will retransmit the orphaned result.
  2. If that does not help, run /compact. This collapses the current conversation into a compact summary and resets the internal session state into something coherent.
  3. After /compact, ask Claude in plain language to continue what it was doing. If you reissue the same tool call, change one argument (for example add -maxdepth 3 to find) so you do not reproduce the original blowup.
  4. If the session is truly stuck, open a fresh Claude Code window and paste the /compact summary as the first message. This is far less painful than starting from zero.

Resist the urge to spam /cancel. Repeated cancels usually deepen the inconsistency and make recovery harder.

Root cause fixes by pattern

Recovery handles today. Prevention handles tomorrow.

MCP responses that are too big

This is the failure mode I have hit most often. If you build an MCP server with a tool like search_files or list_tickets, the result size depends entirely on the caller's query. A bad query can push you past the ceiling instantly.

// Before: returns everything in one shot
server.tool("search_files", async ({ query }) => {
  const all = await db.search(query);
  return { content: all.map(toJSON) };
});
 
// After: hard cap plus cursor-based continuation
server.tool("search_files", async ({ query, cursor, limit = 20 }) => {
  const page = await db.searchPaged(query, { cursor, limit });
  return {
    content: page.items.map(toJSON),
    nextCursor: page.nextCursor,
  };
});

Two rules I keep: cap each tool response at a few tens of KB, and expose a cursor so Claude can ask for the rest in subsequent calls. Claude is excellent at iterating; one fat response is slower in practice than three lean ones.

Bash output that overflows

The same ceiling applies to Bash output. Before pressing Enter on a command, take a beat and think about how many lines it might emit.

# Risky: unknown output size
grep -r "TODO" .
 
# Safer: measure first, sample second
grep -rl "TODO" . | wc -l
grep -rl "TODO" . | head -50
 
# Or stash the full result and return a summary
grep -r "TODO" . | head -200 > /tmp/todo.txt && wc -l /tmp/todo.txt

In my own projects I keep a .claude/commands/safe-grep.md slash command that bakes these guards in, so I never have to remember them in the moment.

ToolUseId / ToolResultId mismatch

If you press /cancel and then immediately type a new prompt, the unsent ToolResult lingers and the next tool call can fail to register. My fix is small but disciplined: after any /cancel, the very next message I send is a sentence like "stop here, summarize where we are, and wait." It feels like a detour, but it is the fastest path back to a clean state.

Streaming disconnects

Most disconnects I see happen during VPN reconnects or when a laptop roams between Wi-Fi access points. For any long-running task (a migration, a heavy refactor, a large build), I now:

  • Pin the connection to wired Ethernet or a known-stable Wi-Fi network
  • Pause cloud sync and background updates that might saturate the link
  • Run long Bash jobs under nohup or inside tmux, then Read the result file once it lands

My grandfathers were both carpenters who built and restored shrines in Japan. They taught me, just by example, that long jobs are won in the preparation. The same is true for long Claude Code sessions.

A safety net when nothing else works

If you reach the point where the session refuses to recover, here is my last-resort routine:

  1. Try claude /resume in a new tab to see if the previous session can be reattached
  2. If not, open a fresh session and feed it a pre-written summary like cat .claude/last_session_summary.md
  3. Add a line to your project's CLAUDE.md instructing Claude to start each recovery by running git status and git log -3 and reporting the current state

That third item is plain but powerful. Treat it as a handover note for your future self, the same way I think about leaving something useful behind for my kids who live apart from me.

One small thing to try today

If this error has bitten you more than once, paste these two lines into your project's CLAUDE.md today:

- For Bash grep/find, always run `wc -l` first to check the size before fetching results
- MCP tools must paginate; never return more than ~20 items per call

That alone has cut the frequency of "Tool result could not be submitted" by more than half in my own workflow. Thanks for reading, and I hope this saves you the afternoon it once cost me.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-04-26
Untangling Claude Code's 'Authorization Failed' Error — OAuth, MCP, and Dynamic Client Registration
Why Claude Code suddenly throws 'authorization failed' or 'incompatible auth server: does not support dynamic client registration', and what to actually do about it. A practical walkthrough of OAuth, MCP server requirements, and the real fixes that work in production.
Claude Code2026-07-18
The MCP Server I Declared Vanished from the List — Designing Config for a Namespace You Share with the Vendor
When a vendor reserves an MCP server name, your .mcp.json declaration goes quiet instead of failing. Here is the preflight check and prefix convention I use to turn that silent gap into a loud stop before an unattended run.
Claude Code2026-07-16
The Permission Rules You Added for Safety Are Taxing Every Turn — Auditing the Ruleset Without Loosening It
Version 2.1.209 fixed the per-turn slowdown from large deny/ask rulesets, but the design debt in your rules is still yours. Here are the audit scripts, a shadowing detector, a turn-timing harness, and how to fold enumerated rules into prefix rules safely.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →