[BUG] API Error 400 - The request body is not valid JSON: str is not valid UTF-8: surrogates not allowed - mid-conversation error

Status Open
Reported on v2.1.160
Maintainer reply None cached
Activity 8 comments · opened Jun 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Error appeared mid-conversation without sending any images and have to start new chat and its not remember anything where left from

What Should Happen?

its not shows this error middle of Claude code conversation as its break all flows of work

Error Messages/Logs

API Error: 400 The request body is not valid JSON: str is not valid UTF-8: surrogates not allowed: line 1 column 1 (char 0)

Steps to Reproduce

Start a conversation in Claude Code (VS Code)
Continue conversation for several exchanges
Error appears without any file/image uploads

It happen since last 3 days only

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

last version also get error

Claude Code Version

2.1.160

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗

8 Comments

MC972Dot · 2 months ago

This is happening to me as well, please fix this :-)

rwinslow-at-premier · 2 months ago

Also happening to me. Went through extensive debugging effort with separate Claude session, analyzing files in project context and memory, concluding that it's a bug, and referring me to the issues list. That Claude suggested I mention: "project has a .claude/ directory with ~110KB of context markdown files and 25 custom agent definitions, error triggers on first prompt after Claude Code autonomously runs tools (git status + file search), and it recurs across sessions."

jessebarton · 2 months ago

We are also having the same problem. When uploading regardless of what we upload. Images included.

ChrisLivettEH · 1 month ago

I keep getting this issue today

BarriePocock · 1 month ago

Adding a distinct data pattern from a small fleet of Windows 11 machines (Claude Code desktop app, long-lived sessions): storms + re-accumulation + relaunch-cure, which may help narrow where the lone surrogate enters.

Environment/workload: very long-lived sessions (hours to all day), heavy inbound emoji-dense chat content arriving via MCP tooling (Microsoft Teams messages), frequent screenshot pastes.

Pattern observed (5 episodes across 2 machines, 2026-07-05 → 2026-07-06):

  • Starts as a single mid-conversation 400 ... surrogates not allowed: line 1 column 1 (char 0) with no image in the failing turn, escalating to storms — 4+ consecutive turns rejected. Notably, tool-side work in the turn still executes; only the reply/API call dies.
  • Full app relaunch stops it immediately and reliably (proven three times). Starting a fresh conversation without relaunching did not clear it.
  • After a relaunch-cure, the error re-accumulated within ~14 hours in a heavy session — frequency appears correlated with session age plus emoji/image volume, not with any specific message.

Client-side content ruled out on our side: we ASCII-hardened every log/notification surface our own tooling feeds into the session and hex-verified recent lines pure ASCII — the 400s continued regardless. Combined with char 0 (whole-body rejection) and the relaunch-flush behavior, this points at a lone surrogate persisting in client-side request assembly state (message-history windowing / truncated tool-result or notification buffers that get re-sent every turn), consistent with the surrogate-pair-splitting analysis in #72995.

Episode windows if server-side correlation helps (SAST/UTC+2): 2026-07-05 06:57–10:27 (storm), 2026-07-05 18:07–18:32 (storm), 2026-07-06 ~08:30 (single), 2026-07-06 ~10:07 (second machine).

VitorMRCNeves · 1 month ago

Im getting this same error while using Claude Cowork in Windowns and asking it to read PDF/Docx files

goodwinb99 · 1 month ago

Adding a data point that points at a network middlebox buffering the SSE stream as a root cause for the no-image / mid-conversation variant of this error.

Environment: macOS, VSCode extension (native/embedded), Claude Code v2.1.201, sitting behind Netskope Secure Web Gateway with TLS inspection (SSL decryption) enabled.

What I observe when it fails:

  • 400 ... str is not valid UTF-8: surrogates not allowed: line 1 column 1 (char 0) fires mid-response, with no image attached and nothing queued — including while Claude is still "thinking."
  • The token counter and the "thought for Xs" indicator never appear on the failed turn — i.e. the terminal SSE events (the message_delta carrying usage, and message_stop) never arrive cleanly, so the assistant turn is left partial.
  • Most tellingly: with the gateway in path, there's a long pause and then the entire response lands in one burst, instead of streaming token-by-token as it's generated. This is the textbook signature of full-response buffering — the gateway holds the whole response body until it's complete before forwarding. With the gateway off — or on a VM that isn't behind Netskope — responses stream incrementally and I do not hit this error.

Hypothesis: the SWG buffers and re-chunks the text/event-stream response for inspection, and a chunk boundary can land in the middle of a multi-byte UTF-8 sequence (or a surrogate pair). The client reassembles a lone/unpaired surrogate into the in-flight assistant message; that surrogate is then replayed in the message history on the next request, so the API rejects the entire body → 400 surrogates not allowed on every subsequent turn.

The corruption is in-flight, not persisted. After a failure I byte-scanned the session .jsonl (737 entries) and found zero lone surrogates anywhere — the stored assistant turns are clean UTF-8. Restarting VSCode / reopening the Claude tab recovers the session. That's consistent with stream-level mangling rather than a corrupted stored transcript.

Differential test to confirm: toggle the SSE-buffering middlebox (Netskope SWG in my case) off → streaming resumes token-by-token and the 400 stops. Anyone hitting the no-image variant is likely behind a proxy / gateway / endpoint-AV that buffers SSE. A do-not-decrypt / bypass exception for api.anthropic.com on the gateway also resolves it.

Possible client-side hardening: decode the SSE byte stream as UTF-8 across chunk boundaries (hold an incomplete trailing multi-byte sequence until the next chunk arrives) instead of decoding per-chunk, and/or sanitize lone surrogates out of assistant content before persisting or re-sending it — so a badly-chunked stream degrades gracefully instead of bricking the conversation.

Likely the same underlying issue as the image-attach reports (e.g. #69781), where the encode/decode path produces the same lone-surrogate symptom.

allenfortes · 1 month ago

Confirming this on Windows 11, VS Code extension, CLI + extension both on v2.1.205 (latest as of 2026-07-09).

Reproduction:

  1. Paste a screenshot (via built-in Windows Snipping Tool) into the Claude Code chat along with a short prompt. Works fine.
  2. Paste a second screenshot into the same conversation. This request fails with:

API Error: 400 The request body is not valid JSON: str is not valid UTF-8: surrogates not allowed: line 1 column 1 (char 0)

  1. From that point on, every subsequent request in the same session fails with the same error — even plain text messages with no image attached. The corrupted turn appears to stay in conversation history/context and gets re-sent (and re-rejected) on every following request. Starting a new session is the only way to recover.

Ruled out while investigating:

  • Not a remote/VDI/RDP session — local machine.
  • Same screenshot tool (Windows Snipping Tool) used on a second laptop that does not reproduce the issue.
  • No clipboard manager installed.
  • Not a DPI/display-scaling issue — tested at 100% scaling on the affected laptop, still reproduces.
  • Reproduced on both v2.1.204 and v2.1.205.

This looks distinct from the emoji/truncation-boundary surrogate fixes shipped in v2.1.172/v2.1.187 — no emoji or special characters involved, just repeated image pastes.

Likely cause found: the affected laptop has Netskope's endpoint agent installed and running (EPDLP endpoint-DLP module + STAgent SSL-interception/traffic-steering module). Netskope's DLP inspects clipboard content, and its SSL-interception agent decrypts/inspects/re-encrypts HTTPS traffic (including this app's API calls) for content scanning before forwarding it. That would explain the 400 coming from the API itself rather than a client-side crash — the request body is likely being corrupted in-transit during Netskope's inspection/re-encoding of the payload, which is more likely to surface on larger binary payloads like base64-encoded images than plain text. My other, unaffected laptop does not have this agent installed. If others hitting this are on a corporate network with a TLS-inspecting/DLP proxy (Netskope, Zscaler, etc.), that's worth checking — the fix on my end will likely be an SSL-inspection/DLP bypass exception for Anthropic's API domains rather than anything in Claude Code itself.

(Secondary, likely unrelated: the affected laptop has no admin rights so runs Claude Code's "native" self-contained binary rather than a global npm install — mentioning in case it's relevant, though the Netskope finding above seems the stronger lead.)

Also reproduces in the plain claude CLI, not just the VS Code extension — same error, same "every subsequent request fails" behavior. Since the CLI and the VS Code extension use different mechanisms for attaching/pasting images, this rules out anything specific to VS Code's own clipboard-paste handling and points at something shared by both entry points: either the core CLI binary's request/encoding logic, or the network path (which for me means Netskope, intercepting every claude.exe flow to api.anthropic.com regardless of which entry point launched it).