Skip to content

fix: guard null visible range in indent guides prepareRender (fixes #244370) #327584

Description

@vs-code-engineering

Summary

IndentGuidesOverlay.prepareRender crashes with TypeError: Cannot read properties of null (reading 'left') at indentGuides.ts:138 because it dereferences the result of ctx.visibleRangeForPosition(...) with a non-null assertion (!.left), while that method's declared contract is HorizontalPosition | null. When a guide's column has no visible range in the current frame (position not yet laid out, GPU/DOM viewline transition, or scroll/wrap edge), the method legitimately returns null and the ! bypass throws. Notably, every sibling call to visibleRangeForPosition in the same function already handles null safely (?.left ?? 0 on the leftOffset at line 132, and ?.left ?? (left + this._spaceWidth) for the horizontal-line width at lines 154-157) — only the vertical-guide left computation used the unsafe !.

Fixes #244370
Recommended reviewer: @hediet

Culprit Commit

The non-null assertion pattern predates the current telemetry window and lives in the editor indent-guides rendering path. The closest owning change is the line-height refactoring series by @hediet (a9ab31d "Refactors: Reduces assumptions about line height." and its reapply 5faa55a), which reworked how guide columns map to visible ranges. The exact introduction of the ! could not be pinned down precisely because the working tree is a shallow clone (depth 1), so git blame history is unavailable. The bug is a latent contract violation rather than a fresh regression.

Code Flow

sequenceDiagram
    participant DOM as dom.ts scheduler
    participant ViewPart as view.ts
    participant Overlays as viewOverlays.ts
    participant Guides as indentGuides.ts prepareRender
    participant Ctx as RenderingContext

    DOM->>ViewPart: safeInvokeNoArg -> prepareRender
    ViewPart->>Overlays: prepareRender(ctx)
    Overlays->>Guides: prepareRender(ctx)
    Guides->>Ctx: visibleRangeForPosition(Position(line, guide.column))
    Ctx-->>Guides: null (no visible range this frame)
    Note over Guides: null! .left -> TypeError
Loading

Affected Files

  • src/vs/editor/browser/viewParts/indentGuides/indentGuides.tsprepareRender guide loop: replaced the unsafe non-null assertion with a null check.

Repro Steps

Not reliably reproducible on demand; it is a timing/layout-edge crash. It occurs when prepareRender runs for a guide whose column is not currently resolvable to a visible range — e.g. during rapid scrolling, viewline recycling, GPU renderer transitions, or wrapped-line layout churn while indent/bracket-pair guides are enabled. Telemetry shows real-world hits from the editor render loop (view.ts -> viewOverlays.ts -> indentGuides.ts).

How the Fix Works

Chosen approach (src/vs/editor/browser/viewParts/indentGuides/indentGuides.ts): The left computation for a guide with a real model column (guide.column !== -1) previously did ctx.visibleRangeForPosition(new Position(lineNumber, guide.column))!.left. The ! is the type-system bypass: it asserts non-null on a value the method's signature declares as HorizontalPosition | null. This is fixed at the bypass site itself — not at a downstream reader and not by coercing to a benign default — by removing the assertion, checking the returned value, and continue-ing the guide loop when the range is absent so the guide is simply not emitted for this frame (it renders on the next frame once layout resolves). This matches the existing null-handling already used by every other visibleRangeForPosition call in the same function, so behavior is consistent and no error is masked: visibleRangeForPosition returning null is a legitimate, expected outcome of its contract, not invalid data produced upstream. There is no "producer of bad data" to fix — the producer already correctly returns null; the consumer's ! was the defect.

After this change, indentGuides.ts:138 cannot produce the TypeError because the code no longer dereferences the return value of visibleRangeForPosition without first confirming it is non-null; the continue path skips the guide instead.

Alternatives considered: Falling back to leftOffset/0 like line 132 was rejected because a guide whose column is not layout-resolvable would be painted at the wrong x-position (visual glitch) rather than omitted; skipping the guide for the frame is visually correct and self-heals on the next render.

Recommended Owner

@hediet — already the assignee of #244370, owner of the editor indent-guides / bracket-pair-guides area, and author of the line-height refactoring commits that shaped this rendering code.

Generated by errors-fix · opus48 200.1 AIC · ⌖ 23.6 AIC · ⊞ 17.1K ·


Note

This was originally intended as a pull request, but the git push operation failed.

Original error: The process '/usr/bin/git' failed with exit code 128

Workflow Run: View run details and download bundle artifact

The bundle file is available in the agent artifact in the workflow run linked above.

To create a pull request with the changes:

# Download the artifact from the workflow run
gh run download 30241462016 -n agent -D /tmp/agent-30241462016

# Fetch the bundle into a temporary ref, then update the local branch
git fetch /tmp/agent-30241462016/aw-microsoft-vscode-fix-indent-guides-null-visible-range-244370.bundle refs/heads/fix/indent-guides-null-visible-range-244370:refs/bundles/create-pr-fix-indent-guides-null-visible-range-244370-21c8e74b0a007704-5c845df9
git update-ref refs/heads/fix/indent-guides-null-visible-range-244370-21c8e74b0a007704 refs/bundles/create-pr-fix-indent-guides-null-visible-range-244370-21c8e74b0a007704-5c845df9
git checkout fix/indent-guides-null-visible-range-244370-21c8e74b0a007704
# Ensure the working tree matches the updated branch
git reset --hard
# Remove the temporary bundle ref
git update-ref -d refs/bundles/create-pr-fix-indent-guides-null-visible-range-244370-21c8e74b0a007704-5c845df9

# Push the branch to origin
git push https://github.com/bryanchen-d/vscode.git fix/indent-guides-null-visible-range-244370-21c8e74b0a007704

# Create the pull request
gh pr create --title 'fix: guard null visible range in indent guides prepareRender (fixes #244370)' --base main --head bryanchen-d:fix/indent-guides-null-visible-range-244370-21c8e74b0a007704 --repo microsoft/vscode

Activity

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions