the code editor collides with itself: two panels, one model, two buffers
The "two Monaco editors sharing a model" elimination asked which OTHER
component mounts Monaco and never asked whether the code editor collides with
itself. It does — the panel is addable to a dashboard twice, and useEditorState
keeps files in a plain useState, so two panels hold two independent buffers for
one globally-keyed model.
Verified against @monaco-editor/react@4.7.0's built source rather than inferred.
Model lookup is getModel(uri) || createModel(value), so the second mount adopts
the first panel's buffer and ignores its own freshly-read value. The value-sync
effect then overwrites the shared model with executeEdits. And the flag that
suppresses onChange during that write is per-instance, so one panel's
programmatic write fires the OTHER panel's onChange — which CodeEditor answers
with setContent(path, value). The other panel's buffer becomes this one's
content and goes dirty with no keystroke: dirty tab, content nobody typed, disk
untouched, fixed by reopening. Exactly the reported shape.
Unmount also disposes the shared model (keepCurrentModel defaults false), and
key={activeFile.path} means that fires on every tab switch, not only on panel
close — so one panel can dispose a model another is still displaying.
Not yet a closed case: nothing in the app writes job output into
useEditorState, so this produces the right shape but does not explain where the
log text comes from. No fix shipped — the two candidates (per-panel model URIs
vs sharing the state to match the shared model) differ in whether Monaco's
TypeScript resolution keeps working, and that is the owner's call. Trap stays
armed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: f7a62308-0977-4cf4-aa29-c020853fd420
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
id: known-bugs/background-job-logs-appeared-inside-an-open
|
||||
title: "Background job logs appeared INSIDE an open file in the code editor"
|
||||
title: 'Background job logs appeared INSIDE an open file in the code editor'
|
||||
theme: known-bugs
|
||||
status: open
|
||||
created: 2026-08-16
|
||||
@@ -60,6 +60,23 @@ One thing to rule out first, because it is mine and it is recent: `2b70a570` gav
|
||||
panels open on the same file now share one model. That should be an improvement, but it is a change
|
||||
in exactly the layer that turned out to be involved.
|
||||
|
||||
**2026-08-25 — that suspicion was right, and the "ruled out" row above was wrong.** The elimination asked
|
||||
which OTHER component mounts Monaco and never asked whether the code editor collides with **itself**. It
|
||||
does: the panel is addable to a dashboard twice, and `useEditorState` keeps `files` in a plain `useState`,
|
||||
so two panels hold two independent buffers for one globally-keyed model. Verified in
|
||||
`@monaco-editor/react@4.7.0`'s source: model lookup is `getModel(uri) || createModel(value)` so the second
|
||||
mount's value is ignored, the value-sync effect then overwrites the shared model with `executeEdits`, and
|
||||
**the flag that suppresses `onChange` during that write is per-instance** — so one panel's programmatic
|
||||
write fires the OTHER panel's `onChange`. `CodeEditor` responds with `setContent(path, value)`: the other
|
||||
panel's buffer becomes this one's content and goes dirty with no keystroke. Unmount also disposes the
|
||||
shared model (`keepCurrentModel` defaults false), and `key={activeFile.path}` means that happens on every
|
||||
tab switch, not just on panel close.
|
||||
|
||||
That reproduces the symptom's exact shape — dirty tab, content nobody typed, disk clean, fixed by
|
||||
reopening. It does **not** explain how job output becomes one of those buffers, and nothing in the app
|
||||
writes job output into `useEditorState`. So the trap stays armed; it is still the only thing that can name
|
||||
where the text came from. Full write-up in `docs/editor-buffer-corruption.md`.
|
||||
|
||||
Worth noting because it is the reason to look at all: an editor that can show content the file does
|
||||
not contain is a correctness problem even when it never writes — the next person's instinct will be to
|
||||
save the file to "fix" it.
|
||||
|
||||
Reference in New Issue
Block a user