Repository navigation
Fix workspace reorder crash for a pinned group's anchor - #13688
Merged
Merged
Conversation
A pinned group whose rows fill the sidebar makes clampedReorderIndex return tabs.count for the group's anchor, which is not individually pinned. The coordinator then removes the row and inserts at that index into an array one shorter, trapping in Array.insert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
clampedReorderIndex tiered a workspace by its own isPinned flag, but a group anchor renders pinned when its group is pinned. With every row group-pinned, the anchor was treated as unpinned and pushed to pinnedCount == tabs.count, one past the last legal insert index after the coordinator removes the row. Tier by the rendered pin (isGlobalPinnedRow) and cap the unpinned branch at tabs.count - 1. The iOS move policy and its host-order simulator mirror the macOS clamp, so they get the same change to keep predictions in agreement. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 10 seconds. View limit detailsLimit 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. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (4)
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. Comment |
teamleaderleo
enabled auto-merge (squash)
September 22, 2026 15:10
Contributor
|
All contributors have signed the CLA ✍️ ✅ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #13417. Closes #13505.
Problem
WorkspacesModel.clampedReorderIndexcould returntabs.count.WorkspaceReorderCoordinatorremoves the row and then inserts at that index, into an array one shorter, which traps inArray.insert.This happens when every row in the sidebar belongs to a pinned group and the moved workspace is that group's anchor:
clampedGroupedMemberReorderIndexreturnsnilfor anchors.isPinned, which isfalsebecause group pin is independent of per-workspace pin.isGlobalPinnedRowdoes count the anchor as pinned, sopinnedCount == tabs.count, andmax(clamped, pinnedCount)pushed it one past the end.The index isn't coming from the client. Line 298 already clamps any requested index, and the out-of-range value is produced at the end of the function. That's why the client-side clamp workaround reported in #13505 didn't help.
Repro: one pinned group with anchor A and member B, neither individually pinned;
workspace.reorder {workspace_id: A, index: 0}givestoIndex = 2on a 2-element array.Resulting behavior
isGlobalPinnedRow). A pinned group's anchor clamps into the pinned tier like the rest of its group, instead of being treated as unpinned and pushed below the pinned rows.tabs.count - 1, so no pin configuration can produce an index past the end.true, and the order stays[A, B].MobileWorkspaceMovePolicy, andMobileWorkspaceHostOrderSimulatorin its tests, mirror this clamp to predict host order, so they get the same two changes. The iOS side guarded its insert, so it never crashed, but it predicted[B, A]for this case.Validation and remaining gap
WorkspaceReorderPinnedGroupAnchorTestsonly. Locally, both tests fail:swift test --filter WorkspaceReorderPinnedGroupAnchorrecords 6 issues, with every requested index from -1 to 99 clamping to 2 on 2 rows. The coordinator test checks the clamp before reordering, so the unfixed code fails instead of trapping the test process. Commit 2 was pushed right behind it, so CI only ran on the fixed head.swift testinPackages/macOS/CmuxWorkspacespasses 230 tests in 32 suites, and inPackages/iOS/CmuxMobileShellModelpasses 392 tests in 45 suites.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Fixes a crash when reordering the anchor of a pinned group whose rows fill the entire sidebar.
clampedReorderIndexcould returntabs.countfor a group anchor whose group is pinned but whose workspace isn't individually pinned. The reorder coordinator then removed the row and inserted at that out-of-range index, trapping inArray.insert. The reorder now tiers by how the row renders and caps the index attabs.count - 1.Bug Fixes
isGlobalPinnedRow) so a pinned group's anchor clamps like the rest of its group instead of being treated as unpinned.tabs.count - 1so no pin configuration can produce an index past the array end.MobileWorkspaceMovePolicyand its host-order simulator so iOS predictions agree with macOS.Written for commit 0ac3bfb. Summary will update on new commits.