Skip to content

[CodeMirror] Editor crashes from the @codemirror/view tile rendering rewrite (6.39.0+) #1317

Description

@microbit-matt-hillsdon

Claude generated from Sentry error log analysis.

Seven Sentry groups, ~1,880 events since mid-July and ~18/day currently, all resolve to one cause: the content-drawing rewrite in @codemirror/view 6.39.0. All are confirmed present in v3.1.11.

Why we think it is one cause, and why now

src/tile.ts first appears in @codemirror/view at tag 6.39.0 (upstream commit 56466f1, "Start on overhauling the content drawing system"). The 6.39.0 changelog does not advertise the rewrite; it lists block wrappers and "Properly handle bidirectional text in posAtCoords".

We crossed that boundary in one step:

@codemirror/view
v3.1.6, v3.1.7 6.26.3
v3.1.8 (2 Sep 2026) 6.43.9
v3.1.9 – v3.1.11 6.43.11

The lockfile moved 6.26.3 → 6.43.4 in 925f3b2e ("Secure npm dependencies and update packages", #1247) on 15 July 2026. Every group below has a Sentry firstSeen of 15 or 16 July 2026 on dev builds, and reached production with v3.1.8. That is the evidence for attribution: the groups did not exist before the bump and appear the day of it.

This is the bug #1297 was reaching for. That issue spotted the 17-minor view jump and guessed at "a state field resolving a stale position against the document"; the tile rewrite is the mechanism. #1297 was closed before the tile frames were identified.

The groups

Sentry Error Innermost frame Events First seen
3QG TypeError: Right side of assignment cannot be destructured TilePointer.advance 553 15 Jul
3QN RangeError: Invalid position N in document of length M InlineCoordsScanText.lineAt 542 16 Jul
3QH Error: No tile at position N DocTile.resolveBlock 410 15 Jul
3QE Error: No tile at position N DocTile.resolveBlock 377 15 Jul
3TD HierarchyRequestError CompositeTile.syncinsertBefore 1 10 Sep
3TC HierarchyRequestError CompositeTile.syncinsertBefore 1 10 Sep
3TE TypeError: Right side of assignment cannot be destructured TilePointer.advance 1 10 Sep

The three single-event groups appeared for the first time on v3.1.11.

Triage trap: Sentry blames our files

Sentry's culprit is the outermost in-app frame, so the same upstream throw is filed against whichever of our extensions happened to dispatch the update. Group by innermost frame, not culprit. Affected culprits seen so far:

  • src/editor/codemirror/lint/editingLine.ts:40
  • src/editor/codemirror/language-server/view.ts:38
  • src/editor/active-editor-hooks.ts (EditorActions)

In each case our code only called view.dispatch(...); the throw is inside @codemirror/view.

Two groups are mixed and predate tiles, so their lifetime counts overstate the tile share — treat only their recent events as tile crashes:

  • 31K, 74 events, first seen 5 Mar 2026
  • 31N, 160 events, first seen 6 Mar 2026

Stack traces

Outermost first; the last frame is where it threw.

TilePointer.advance — reached while applying a DOM change from typing:

DOMObserver.flush (@codemirror/view)
  applyDOMChange
    EditorView.dispatch
      EditorView.update
        DocView.update
          DocView.updateInner
            DOMObserver.ignore
              TileUpdate.run
                TileUpdate.preserve
                  TilePointer.advance      <- throws

DocTile.resolveBlock — reached while drawing the selection layer during measure:

EditorView.measure (@codemirror/view)
  measured
    selectionLayer.markers
      rectanglesForRange
        drawForLine
          DocView.coordsAt
            DocTile.resolveBlock           <- throws "No tile at position N"

InlineCoordsScan — reached from mousedown, converting coordinates to a position:

InputState.handleEvent (@codemirror/view)
  InputState.runHandlers
    handlers.mousedown
      basicMouseSelection
        InlineCoordsScan.scanText
          InlineCoordsScan.scan
            InlineCoordsScan.baseDirAt
              InlineCoordsScan.bidiSpansAt
                Text.lineAt (@codemirror/state)   <- throws, position past doc end

Note this one lands in the bidi path, and "Properly handle bidirectional text in posAtCoords" is a 6.39.0 changelog item.

CompositeTile.sync — reached from undo:

undo (@codemirror/commands)
  EditorView.dispatch
    EditorView.update
      DocView.update
        DocView.updateInner
          DOMObserver.ignore
            CompositeTile.sync
              CompositeTile.sync
                CompositeTile.sync
                  insertBefore (native)    <- throws HierarchyRequestError

Shared shape

All four are the view resolving against a document it no longer matches: positions past the document end, a tile missing at a position, or a DOM node inserted under the wrong parent. Reported positions exceed the reported document length by a small margin (single digits to low tens).

Breadcrumbs are consistent across sessions: a click inside .cm-line.cm-activeLine, then typing, then the throw. One session on 10 Sep produced Selection points outside of document, Invalid position, No tile at position and HierarchyRequestError within the same few seconds, which is further reason to treat them as one fault rather than four.

Upstream status

Not fixed. 6.43.11 is the newest release, and the only commit after it upstream is 7b45dd4 ("Use visualLineSide in moveToLineBoundary"), which is unrelated. Worth reporting upstream with these traces.

Mitigations to consider

  • Pin @codemirror/view to an exact version, as we did for @codemirror/state in 7238efda and for @codemirror/commands. package.json currently has ^6.26.3, which is what allowed a rendering rewrite in via lockfile maintenance.
  • 6.38.x is the last pre-tile release, so pinning back there would confirm causation if we want certainty before reporting upstream.
  • We have no reproduction yet. The measure/selection-layer trace suggests one may be reachable by driving selection while an async decoration source updates, which is the shape of the older [CodeMirror] Invalid position errors due to stale tooltips #1053.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions