Built-in Write tool: large escape-dense content intermittently yields malformed tool-input JSON; retry resends identical payload and also fails

Resolved 💬 1 comment Opened May 17, 2026 by jonathannzhao Closed Jun 16, 2026

Environment

  • Claude Code 2.1.143
  • Windows 11
  • Model: claude-opus-4-7

Summary

When the model issues a Write call whose content is large AND escape-heavy, the tool_use input JSON it produces is malformed, and Claude Code reports it cannot be parsed ("malformed, could not be parsed"). The automatic retry re-issues the byte-identical payload and fails the same way. The file is never written and the work is lost.

Evidence (single session transcript)

| Tool call | output_tokens | Result |
|-----------|---------------|--------|
| Read / Grep / Edit / small Write | 1400-2500 | success |
| Write (large doc) | 2948 | failed |
| Write (large doc) | 4054 | failed |
| Write (large doc) | 5402 | failed |
| Write (large doc) | 6496 | failed |

Every failure was a Write carrying a full document (README, project config, two tutorials) dense with Windows paths (D:\...), registry paths (HKEY_CURRENT_USER\...), fenced code blocks, JSON snippets, and native-messaging escape examples (literal \n, \\). Every success was a light-payload Read/Grep/Edit/small Write.

Likely mechanism

The file content is transmitted as a JSON string in the tool_use input: every backslash must be doubled, every quote escaped, every newline becomes \n. The model emits this escaped JSON token by token. A document that is about escaping nests escapes further. The probability of at least one malformed escape sequence grows with content length x escape density, and a single bad escape makes the whole tool-input JSON unparseable.

This is NOT a fixed size limit: a short but escape-dense file can fail while a long plain-prose file succeeds. The proximate variable is escape density, not token count. The ~2500-token boundary visible above is an artifact of this particular sample (all large calls happened to be escape-dense documents, all small calls happened to be light payloads), not a hard threshold.

Claude Code-side issues (independent of model behavior)

  1. On a tool-input parse failure, the retry resends the identical large payload -- guaranteed to fail again. The retry should change strategy (e.g. a small Write for the header plus chunked Edit appends), not repeat the same call.
  2. No fallback to chunked writing for large content.
  3. The error gives the model/user no actionable hint (e.g. "split into smaller Write/Edit calls").

Possibly related

#50534 (large Write stream idle timeout) -- same "large Write lost, manual chunking is the only workaround" family, different proximate error.

Repro

On Windows, ask Claude Code to create in a single Write a long markdown file full of Windows paths, registry keys, fenced code blocks, and backslash-escape examples.

Ask

  • On tool-input parse failure, retry with a chunked strategy instead of resending the same payload.
  • Optionally auto-chunk large Write content internally.
  • Surface a clearer error advising the chunked approach.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗