microsoft / microsoft/vscode

Multi-diff editor renders phantom repeated file headers (wrong row identity) after scrolling a ~30-file diff

Open
#326,702 1 comment 4 reactions 1 assignee Claimed by @hediet View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Type: Bug

VS Code version: 1.129.0 and 1.129.1 (both affected)
OS version: macOS 15.5 (Darwin 25.5.0), Apple Silicon, external 4K display (BenQ EW3270U)

### Summary

The multi-diff editor (opened via the `vscode.changes` command) intermittently corrupts its virtualized rows **after scrolling** a diff with ~30+ resources: many rows render with the **same file header repeated** (one file's basename/dirname/status badge shown 10–20 times) at sliver heights (~35 px), interleaved with thin slices of *other* files' content. Which file becomes the "phantom" repeated header **changes with scroll position**. Clicking into / settling on a row renders that file perfectly; closing and reopening the multi-diff editor always clears the corruption.

### Steps to reproduce

1. An extension opens a multi-diff via `vscode.changes` with ~35 triples `[label, original, modified]` whose sides are URIs of a registered `TextDocumentContentProvider` (custom scheme; every document resolves promptly and correctly — initial render is clean and fully expanded).
2. Scroll up and down through the multi-diff for a while (mouse wheel, varying speed).
3. Observe rows collapsing into repeated phantom headers of a single file with sliver-height content slices from unrelated files.

Synthetic content generator we used (any repo shape with ~35 modified/added/deleted files of a few hundred lines reproduces the input):

```bash
mkdir soup-repo && cd soup-repo && git init -q
for i in $(seq 1 35); do mkdir -p "mod$((i%7))"; { echo "# module $i"; for l in $(seq 1 220); do echo "function fn_${i}_${l}() { return ${l}; } // line ${l}"; done; } > "mod$((i%7))/file_$i.js"; done
git add -A && git commit -qm base
for i in $(seq 1 30); do f="mod$((i%7))/file_$i.js"; sed -i '' "s/return 5;/return 500;/" $f; echo "// appended $i" >> $f; done
for i in 31 32; do rm "mod$((i%7))/file_$i.js"; done
for i in 36 37 38; do echo "// new $i" > "mod$((i%7))/new_$i.js"; done
git add -A && git commit -qm head
```

then, in an extension host, open triples built from `git diff --name-status -z HEAD~1 HEAD` (original = `HEAD~1` side, modified = `HEAD` side, `undefined` sides for A/D) via `vscode.commands.executeCommand("vscode.changes", title, triples)`.

### Observations

- Reproduced on two different days (1.129.0, then 1.129.1 after updating) in a long-lived window; both times only **after scrolling** — the initial render is always correct.
- A fresh instance (`@vscode/test-electron`, only our development extension loaded) given the identical 32-file input rendered cleanly at open; we have not yet caught the corruption in that clean instance, which suggests scroll history / window lifetime is a factor.
- The phantom header's identity tracks scroll position (near the top it repeats an early file, mid-list it repeats a mid-list file, etc.), which smells like the virtualization pool re-binding row templates without updating the header `ResourceLabel` / heights (`src/vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl.ts` ObjectPool + placeholder-height path).
- Rebuilding the editor (close + `vscode.changes` again) reliably clears it; `multiDiffEditor.expandAll` / `collapseAll` do not.
- Our original screen recording shows proprietary code, so it isn't attached; happy to run instrumented builds or provide further diagnostics on request.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.