Skip to content

Hold Files tree reloads while its context menu is open - #14451

Merged
teamleaderleo merged 2 commits into
mainfrom
fix/12914-files-ctrl-click-crash
Sep 25, 2026
Merged

teamleaderleo merged 2 commits into
mainfrom
fix/12914-files-ctrl-click-crash

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Ctrl-clicking a row in the Files sidebar could crash cmux (#12914, 4 reports on 0.64.24 and 0.64.25). Every report has the same stack: AppKit throws from -[NSTableRowData rowViewAtRow:createIfNeeded:] while drawing the context-menu highlight for the clicked row, inside the Core Animation commit that NSContextMenuTrackingSession startMonitoringEvents runs as the menu appears.

AppKit keeps the clicked row index for that highlight until the menu closes. Meanwhile the Files coordinator reloads the outline (reloadData, and reloadItem(_:reloadChildren:) plus re-expansion for every loaded folder) whenever the store changes, and SwiftUI's updateNSView calls the same reloadIfNeeded() synchronously. SwiftUI flushes those updates inside a Core Animation commit, so a reload can land between the highlight row being chosen and being drawn. Store changes are frequent here: hovering a folder prefetches its children, and git status and directory watchers publish too.

The outline now tracks its own context menu with willOpenMenu(_:with:) / didCloseMenu(_:with:). While the menu is open, reloadIfNeeded() records that it owes a reload and returns without touching rows. When the menu closes it runs one catch-up reload on the next main-queue turn, after AppKit has cleared the highlight. Menu actions keep working because each item already carries its FileExplorerNode as representedObject.

The Find results table has the same shape (a context menu over rows that stream in) but is not in the reports; I left it alone here.

Fixes #12914

Testing

  • New FileExplorerContextMenuReloadTests: with three rows loaded, it opens the menu, shrinks the store to one row and reloads (rows stay at 3), then closes the menu and waits up to 2 s for the deferred reload (rows become 1). It runs in the cmux unit lane in CI; I did not build cmux locally.
  • I could not reproduce the crash locally, so the exact trigger (which store change lands inside the popup commit) is inferred from the stack and the code, not observed. The change only delays outline reloads while a Files context menu is on screen.
  • scripts/lint-pbxproj-test-wiring.sh and scripts/check-pbxproj.sh pass.

Checklist

  • Behavior changes have added or updated tests, or Testing says why not

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes the cmux crash on ctrl-clicking a Files sidebar row by holding outline reloads while a context menu is open.

AppKit keeps drawing the context-menu highlight for the clicked row until the menu closes and throws if a reload removes that row underneath it. The outline now tracks its own context menu and skips reloads while one is on screen; a single catch-up reload runs on the next main-queue turn after the menu closes. Menu actions are unaffected since each item already carries its node as representedObject. The Find results table has the same shape but is not in the crash reports, so it is left unchanged.

Testing

  • New FileExplorerContextMenuReloadTests covers the hold-then-catch-up behavior.
  • The crash could not be reproduced locally, so the trigger is inferred from the stack trace and code rather than observed.

Written for commit acee8e6. Summary will update on new commits.

Review in cubic

Ctrl-click on a Files row crashed in -[NSTableRowData rowViewAtRow:
createIfNeeded:] while AppKit drew the context-menu highlight. The
highlight keeps the clicked row index until the menu closes, and the
coordinator reloads the outline from store changes and from SwiftUI's
updateNSView, which can run in the same Core Animation commit that paints
the highlight. Track the menu with willOpenMenu/didCloseMenu on the
outline, skip reloads while it is open, and run one catch-up reload after
it closes.

Fixes #12914

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 4 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 22cdc8e0-5de9-4129-a793-6e50b5e2feb1

📥 Commits

Reviewing files that changed from the base of the PR and between 812288a and acee8e6.

📒 Files selected for processing (4)
  • Sources/FileExplorerNSOutlineView.swift
  • Sources/FileExplorerView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/FileExplorerContextMenuReloadTests.swift

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo
teamleaderleo merged commit c7e79f6 into main Sep 25, 2026
107 of 126 checks passed
@teamleaderleo
teamleaderleo deleted the fix/12914-files-ctrl-click-crash branch September 25, 2026 12:53
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Merged per Leo's direction to land without waiting on full CI. Reviewed adversarially (AppKit ordering checked with a probe: menuNeedsUpdate, then willOpenMenu, then the popup; open/close always pair). Caveat: this head's macOS compile admission never started. It sat queued on blacksmith-6vcpu-macos-26 for about 2.5 hours over three attempts, so the first compile of this change is main's next build. If main goes red in FileExplorerView.swift, FileExplorerNSOutlineView.swift or FileExplorerContextMenuReloadTests.swift, that's this PR.

@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for acee8e6b86, merged 2026-09-25 12:53:02 UTC

  • Not verified at merge: ci-status (not reported), macOS compile admission (in progress)
  • Verified: Web complexity, web-validation, Fast static checks, GhosttyKit release check, guards (17), linux-preflight, macOS admission gate, Testbox broker trust boundary
  • Skipped by policy: browser, Claude wrapper regressions, remote-daemon, suite-coverage, swift-package-tests, web, web-build, web-database-tests, web-tests
  • Full suite: runs on main after merge.

Labeled merged-unverified: if main breaks near this merge, look here first.

@github-actions github-actions Bot added the merged-unverified A judging check was not green at merge; see the merge receipt comment label Sep 25, 2026
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 25, 2026
c055747 ci: parse runner expressions in the fork guard, and gate LINUX_RUNNER on fork PRs (manaflow-ai#14192)
fc112a8 docs(testing): describe how run-e2e.sh actually picks the runner (manaflow-ai#14620)
0f6edfa ci(owned): keep seeds until the disk is actually short, not at a fixed 6 (manaflow-ai#14621)
1b78097 CI: one owned-pool rescue sweeper instead of a rescue run per CI run (manaflow-ai#14602)
c7e79f6 Hold Files tree reloads while its context menu is open (manaflow-ai#14451)
dbb24cb ci: read the owned-pool rescue's Actions API through the route App (manaflow-ai#14499)
36b8063 ci: store each app-host product file once in the product archive (manaflow-ai#14601)
0dba677 CI: run CmuxWorkspaces package tests (manaflow-ai#14592)
2244e98 Fix color detection in native tmux mirrors (manaflow-ai#14175)
3d2478e build: keep every built file in a project group so Xcode reuses its build description (manaflow-ai#14486)
a1a5ae9 ci(cmux-tui): cache cargo builds in the Rust jobs (manaflow-ai#14613)
560e640 ci(owned): keep 8 seeds per mini and pick seeds by cost, not a 2-commit cap (manaflow-ai#14607)
561d317 cmux-debug-cli: find a publish-hq build in the HQ tag app cache (manaflow-ai#14579)
c0aaac7 fix(events): survive receive-timeout reconfiguration churn during replay (manaflow-ai#13888)
3bd994a fix: keep split zoom when the zoomed pane outlives a tab close (manaflow-ai#12853)
ca984c7 Session snapshots can send binding actions to ghostty on a surface that is no longer live (manaflow-ai#12623)
a47d65b settings: expose local tmux session persistence (manaflow-ai#13210)
e3acb25 ci: give an owned Mac's full app rebuild 35 minutes to compile (manaflow-ai#14594)

# Conflicts:
#	.github/workflows/ci-artifact-transport.yml
#	.github/workflows/ci-cache-receipts.yml
#	.github/workflows/ci-guards.yml
#	.github/workflows/ci-macos.yml
#	.github/workflows/ci-owned-pool-rescue.yml
#	.github/workflows/ci-web.yml
#	.github/workflows/ci.yml
#	.github/workflows/cloud-machine-tests.yml
#	.github/workflows/cloud-vm-guest-install.yml
#	.github/workflows/cloud-vm-image-contract.yml
#	.github/workflows/cloud-vm-image-reachability.yml
#	.github/workflows/cloudflare-relay.yml
#	.github/workflows/cmux-skill-contract.yml
#	.github/workflows/cmux-tui-sdks.yml
#	.github/workflows/cmux-tui-spec.yml
#	.github/workflows/cmux-tui.yml
#	.github/workflows/indexnow-tests.yml
#	.github/workflows/iroh-v2.yml
#	.github/workflows/localization-catalog.yml
#	.github/workflows/r2-upload-tests.yml
#	.github/workflows/remote-daemon.yml
#	.github/workflows/repair-nightly-appcast-content-types.yml
#	.github/workflows/required-checks-drift.yml
#	.github/workflows/resolve-dispatch-ref.yml
#	.github/workflows/seed-derived-data.yml
#	.github/workflows/terminal-hang-diagnostics.yml
#	.github/workflows/test-e2e.yml
#	.github/workflows/test-ios.yml
#	.github/workflows/testbox-broker-guard.yml
#	.github/workflows/web-validation.yml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-unverified A judging check was not green at merge; see the merge receipt comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ctrl-click on a row in the Files sidebar panel crashes cmux (NSTableRowData rowViewAtRow context-menu-highlight exception)

1 participant