VS Code: plan review pane shows previous plan version when ExitPlanMode is batched with a plan-file write

Status Open
Reported on v2.1.283
Maintainer reply None cached
Activity 0 comments · opened Sep 28, 2026

Summary

In the VS Code extension, the plan review pane ("Ready for review") can show the previous version of the plan when the model writes the plan file and calls ExitPlanMode in the same tool batch. The approval result contains the new plan, so the user reviews one plan and approves another.

Environment

  • VS Code 1.139.1 (macOS, arm64)
  • Extension anthropic.claude-code 2.1.283 (darwin-arm64), with its bundled CLI

Steps to reproduce

  1. In plan mode, let the model revise an existing plan.
  2. The model emits a Write (or Edit) to the plan file and ExitPlanMode in the same parallel tool batch.
  3. Look at the "Ready for review" pane.

Expected

The pane shows the plan as written by that batch, which is what the user is approving.

Actual

The pane shows the plan as it was before that write. The ExitPlanMode result (the "Approved Plan" text) contains the new version, so what was reviewed and what was approved differ.

Evidence

From Claude VSCode.log: the content of each open_markdown_preview request, compared with the plan on disk at that moment.

| Time | Content sent to pane | Plan on disk | Tool calls |
|---|---|---|---|
| 09:00:51 | previous plan (v0) | v1 | Write + ExitPlanMode, same batch |
| 09:01:41 | v1 | v1 + title edit | Edit + ExitPlanMode, same batch |
| 09:05:31 | v1 + title edit | v2 | Write + ExitPlanMode, same batch |
| 09:09:27 | v2 | v2 ✅ | ExitPlanMode alone |
| 09:13:48 | v2 | v3 | Write + ExitPlanMode, same batch |

The pane lags exactly one version every time the write is batched with ExitPlanMode. It's correct when ExitPlanMode is sent on its own.

Suspected cause

ExitPlanMode's plan field is injected by normalizeToolInput ("The plan content (injected by normalizeToolInput from disk)"), via the plan-file cache. The injection appears to happen before the sibling Write/Edit in the same batch executes, so the snapshot is stale. The webview then forwards permissionRequest.inputs.plan to openMarkdownPreview, which renders it as-is.

Possible fixes:

  • Resolve plan when the permission prompt is shown, after earlier tool calls in the batch have completed.
  • Or re-read the plan file when rendering the preview.

Side note (possibly unrelated)

In the extension host, shutdown() sets planPreviewsDetached = true, and nothing appears to reset it. It also detach()es the open preview panels without disposing them. If the same host object is reused afterwards, openMarkdownPreview would return early and leave a stale panel on screen. This didn't cause the case above, because the log shows the requests were received, but it may be worth checking.

View original on GitHub ↗