You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Editor sitting idle, one CPU core pinned at ~100% indefinitely. A single background worker thread (Worker-N from the gpui_linux dispatcher pool) is stuck in a pure userspace busy loop inside edit-prediction context gathering — specifically edit_prediction_context::identifiers_for_position → language::outline::OutlineItem::body_range.
Related to #57585 (same surface symptom — 100% CPU with tree_sitter frames on top of the stack), but the driver is a different subsystem, so filing separately. In #57585 the loop is SyntaxSnapshot::reparse_with_ranges → ts_parser__recover; that frame does not appear here. This is either a distinct bug or a second way to reach a similar hot path.
Investigation performed by Claude Opus 4.8 running at extra-high reasoning effort ("xhigh"), driving a live gdb session via Claude Code on the affected machine.
Environment
Zed: 1.4.4 (Arch Linux package zed 1.4.4-1, build-id 2f6ddc46bd6985b94e87fb559fe41050c22cbf1b) — newer than the v1.2.6+stable in 100% CPU (tree-sitter reparse loop) #57585
Project open was an Elixir project (ElixirLS v0.30.0), but the loop is language-agnostic — it lives in edit-prediction context gathering, not in the language server (the LSP process was at 0% CPU, mix_compile_noop).
Symptom
Editor idle, one core at ~100% indefinitely. A single background worker thread is in state R continuously. Nothing is logged while CPU stays pinned.
How it was diagnosed
ps//proc showed the CPU was burned by the zed-editor process itself, in one background worker thread — not the language server (Elixir beam.smp at 0% CPU, mix_compile_noop).
/proc/<pid>/task/<tid>/syscall was empty and wchan == 0 → a pure userspace busy loop, no I/O, no blocking. The Zed log had gone silent while CPU stayed at 100% → the loop logs nothing.
Attached gdb to the spinning thread (selected by LWP) and symbolized with Arch debuginfod. Sampled the stack 3× — every sample landed in the same call chain (identifiers_for_position → body_range → tree-sitter cursor walk).
The 3 samples landed at slightly different PCs but always inside frames #2–#3: …::identifiers_for_position → OutlineItem::body_range → tree_sitter cursor walk (goto_first_child_for_point, start_point, Point::partial_cmp).
Root cause (analysis)
The hot loop is in edit-prediction context gathering: edit_prediction_context::identifiers_for_position (edit_prediction_context.rs:636), invoked from fetch_excerpts (:235), repeatedly calling language::outline::OutlineItem::body_range (outline.rs:65). tree_sitter appears at the top of the stack only because body_range walks the syntax tree and compares tree_sitter::Point ranges — but the driver of the spin is the edit-prediction path, not a SyntaxSnapshot reparse. This looks like a non-terminating (or pathological) iteration over outline items / tree-cursor positions while computing identifier excerpts around the cursor.
Note: the already-spinning worker does not recover on its own (it's a synchronous loop that never yields, so it won't re-read settings) — Zed must be restarted to clear the current hang. With edit predictions off, the loop does not reoccur.
For maintainers
Likely worth guarding identifiers_for_position / OutlineItem::body_range against the input shape that makes the tree-cursor walk fail to advance. Happy to provide more detail or additional gdb captures.
Summary
Editor sitting idle, one CPU core pinned at ~100% indefinitely. A single background worker thread (
Worker-Nfrom thegpui_linuxdispatcher pool) is stuck in a pure userspace busy loop inside edit-prediction context gathering — specificallyedit_prediction_context::identifiers_for_position→language::outline::OutlineItem::body_range.Related to #57585 (same surface symptom — 100% CPU with
tree_sitterframes on top of the stack), but the driver is a different subsystem, so filing separately. In #57585 the loop isSyntaxSnapshot::reparse_with_ranges→ts_parser__recover; that frame does not appear here. This is either a distinct bug or a second way to reach a similar hot path.Investigation performed by Claude Opus 4.8 running at extra-high reasoning effort ("xhigh"), driving a live
gdbsession via Claude Code on the affected machine.Environment
zed 1.4.4-1, build-id2f6ddc46bd6985b94e87fb559fe41050c22cbf1b) — newer than thev1.2.6+stablein 100% CPU (tree-sitter reparse loop) #57585gpui_linuxrustc 1.95.0,tree-sitter 0.26.9mix_compile_noop).Symptom
Editor idle, one core at ~100% indefinitely. A single background worker thread is in state
Rcontinuously. Nothing is logged while CPU stays pinned.How it was diagnosed
ps//procshowed the CPU was burned by thezed-editorprocess itself, in one background worker thread — not the language server (Elixirbeam.smpat 0% CPU,mix_compile_noop)./proc/<pid>/task/<tid>/syscallwas empty andwchan == 0→ a pure userspace busy loop, no I/O, no blocking. The Zed log had gone silent while CPU stayed at 100% → the loop logs nothing.gdbto the spinning thread (selected by LWP) and symbolized with Archdebuginfod. Sampled the stack 3× — every sample landed in the same call chain (identifiers_for_position→body_range→ tree-sitter cursor walk).Backtrace (symbolized)
The 3 samples landed at slightly different PCs but always inside frames
#2–#3:…::identifiers_for_position→OutlineItem::body_range→tree_sittercursor walk (goto_first_child_for_point,start_point,Point::partial_cmp).Root cause (analysis)
The hot loop is in edit-prediction context gathering:
edit_prediction_context::identifiers_for_position(edit_prediction_context.rs:636), invoked fromfetch_excerpts(:235), repeatedly callinglanguage::outline::OutlineItem::body_range(outline.rs:65).tree_sitterappears at the top of the stack only becausebody_rangewalks the syntax tree and comparestree_sitter::Pointranges — but the driver of the spin is the edit-prediction path, not aSyntaxSnapshotreparse. This looks like a non-terminating (or pathological) iteration over outline items / tree-cursor positions while computing identifier excerpts around the cursor.Workaround (confirmed it stops recurrence)
Disable edit predictions and restart Zed:
Note: the already-spinning worker does not recover on its own (it's a synchronous loop that never yields, so it won't re-read settings) — Zed must be restarted to clear the current hang. With edit predictions off, the loop does not reoccur.
For maintainers
Likely worth guarding
identifiers_for_position/OutlineItem::body_rangeagainst the input shape that makes the tree-cursor walk fail to advance. Happy to provide more detail or additionalgdbcaptures.