Transport loss writes a fabricated user denial into the session transcript

Status Fixed / completed
Reported on v2.1.215
Maintainer reply None cached
Activity 1 comment · opened Jul 19, 2026 · closed Aug 20, 2026

Summary

When the stdio permission-prompt transport dies with a permission request
outstanding, that request appears to resolve to deny rather than to an error
or interrupted state. A tool result is written into the session transcript
reading:

The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed.

No such denial occurred. No permission dialog was ever shown to me, and I never
clicked deny. This misattributes an action to the user and corrupts the
transcript's record of what happened.

Evidence

~/.claude/projects/<workspace>/ce9d29ce-….jsonl, at
2026-07-19T15:44:24.786Z — roughly 72 seconds after the extension host
crashed:

{"type":"user","message":{"content":[{"type":"tool_result",
 "content":"The user doesn't want to take this action right now. STOP what you are doing and wait for the user to tell you how to proceed."}]}}

The model then wrote a full "I've stopped, here's where things stand" message
and exited cleanly.

Why this is worse than a lost session

The fabricated denial made the session believe it had been told to stop. It
halted deliberately and wrote a handoff summary — so the crash presented as
intended behavior rather than as a failure. I only discovered what had actually
happened by reading the transcript on disk afterwards.

It also means the on-disk record now attributes a decision to me that I did not
make. Anything that later reads these transcripts — resumption, analytics,
debugging, or a human reconstructing the session — will read a user denial that
never happened.

Conditions

Both occurrences landed on a permission boundary. I was running
--permission-mode acceptEdits, so Edit calls pass silently but Bash calls
raise a prompt. Both sessions died precisely there, with a prompt outstanding:

  • one on git rm
  • one on git commit

The transport in use is --permission-prompt-tool stdio.

Steps to reproduce

  1. Run Claude Code in the VS Code panel with --permission-mode acceptEdits.
  2. Get the model to a point where it issues a Bash call that raises a

permission prompt.

  1. While that prompt is outstanding, kill the transport — e.g. Command Palette →

"Developer: Restart Extension Host", or kill -9 the extension host pid.

  1. Read the session transcript at ~/.claude/projects/<workspace>/<uuid>.jsonl.
  2. Observe a tool_result recording a user denial that the user never issued.

Expected behavior

On transport loss, an outstanding permission request should resolve to an
explicit error or interrupted state — something the transcript records as
"permission request failed: transport closed" — not to a denial phrased as a
user decision.

More generally: never write a user-attributed decision into the transcript
unless the user actually made it. A timeout or transport failure is not a denial,
and encoding it as one is a correctness bug independent of whatever caused the
transport to fail.

Environment

| Item | Value |
| --- | --- |
| Claude Code VS Code extension | 2.1.215 (anthropic.claude-code-2.1.215-darwin-arm64) |
| Claude Code CLI | 2.1.133 |
| VS Code | 1.129.1 (arm64) |
| OS | macOS 26.5.2 (build 25F84) |
| Model | claude-opus-4-8[1m] and claude-opus-4-8 |
| Permission mode | acceptEdits |
| Permission transport | --permission-prompt-tool stdio |

See also: https://github.com/anthropics/claude-code/issues/79245 — the chat tab spinning forever after the backend
dies. Independent of this one.

View original on GitHub ↗

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