Skip to content

fix: add per-branch mutex to prevent worktree setup race condition#589

Merged
matt2e merged 4 commits intomainfrom
why-does-goose-set-up-not-get-run
Apr 9, 2026
Merged

fix: add per-branch mutex to prevent worktree setup race condition#589
matt2e merged 4 commits intomainfrom
why-does-goose-set-up-not-get-run

Conversation

@matt2e
Copy link
Copy Markdown
Contributor

@matt2e matt2e commented Apr 9, 2026

Summary

  • Adds a per-branch mutex (WORKTREE_SETUP_LOCKS) so that concurrent calls to setup_worktree (frontend) and setup_worktree_sync (backend/MCP) do not race each other when creating worktrees for the same branch
  • Re-checks the DB for an existing workdir after acquiring the lock to avoid duplicate work
  • Refactors setup_worktree_sync to reuse shared helpers (find_existing_worktree_for_branch, create_worktree_*_with_fallback) instead of inlining equivalent logic
  • Replaces silent unwrap_or_default() on action detection errors with log::warn! for better observability
  • Removes diagnostic info-level logging that was added temporarily to investigate the issue

Test plan

  • Verify that concurrent worktree setup calls for the same branch do not produce duplicate worktrees or errors
  • Verify that prerun actions still run correctly after worktree setup
  • Check logs for proper warn-level messages when action detection fails

🤖 Generated with Claude Code

matt2e and others added 4 commits April 9, 2026 10:49
Add comprehensive logging across all 4 entry points of the setup flow
(create_project, add_project_repo, project_mcp, setup_worktree_and_run_prerun)
to diagnose why `just setup` doesn't run for some projects.

Key changes:
- Log action detection start, mode, results, and failures instead of
  silently swallowing errors with .unwrap_or_default()
- Log prerun action filtering, counts, and working directory
- Upgrade project_mcp debug! to info! so messages are visible at
  default log levels
- Log when setup is skipped due to prior claim

Root cause identified: worktree setup fails when a git worktree for
the same branch already exists at a different project path, causing
create_project to return early before prerun actions ever execute.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a project is created, both the backend (create_project →
setup_worktree_sync) and frontend (setup_worktree) race to set up the
same worktree. The loser fails, causing create_project to bail before
running prerun actions like `just setup`.

Add a per-branch lock (WORKTREE_SETUP_LOCKS) following the existing
REPO_CLONE_LOCKS pattern in git/github.rs. Both callers acquire the
lock after clone/fetch but before the DB check + worktree creation,
so the loser simply hits the DB fast-path and returns immediately.

Also switch setup_worktree_sync to use _with_fallback helper variants
as defense-in-depth, and fix misleading [project_mcp] log prefix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove verbose info! logs added to diagnose the prerun actions issue.
Keep warn! logs for actual failures (detection errors, action failures)
and revert debug→info upgrades in project_mcp.rs back to debug.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove leftover info! log that was missed in the previous logging
cleanup commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@matt2e matt2e requested review from baxen and wesbillman as code owners April 9, 2026 02:11
@matt2e matt2e merged commit b2adb04 into main Apr 9, 2026
5 checks passed
@matt2e matt2e deleted the why-does-goose-set-up-not-get-run branch April 9, 2026 02:14
loganj added a commit that referenced this pull request Apr 9, 2026
…ktree-dis

* origin/main: (45 commits)
  feat(penpal): persist recent files activity across restarts (#595)
  feat: persist open windows, tabs, and geometry across app restarts (#588)
  feat(staged): generate next prefill text when generating notes (#594)
  feat(staged): add "Run again" button to action output dialog (#593)
  feat: queue repo sessions in project MCP with async cancellation fix (#591)
  fix(staged): lowercase "building" subtitle for consistency (#592)
  fix(staged): use completedAt for commit prefill timeline ranking (#590)
  fix: add per-branch mutex to prevent worktree setup race condition (#589)
  feat: add diff commit session launcher (#585)
  fix: avoid error state for empty titled code reviews (#587)
  fix: cancel in-flight auto reviews before manual sessions (#584)
  feat(settings): add repo context search (#583)
  fix(staged): sort timeline items by completion time so queued items appear before completed ones (#568)
  fix: drain queued branch sessions from backend lifecycle (#579)
  fix: restore resume session metadata for resumed actions (#580)
  feat(staged): add purple diff comment theme (#578)
  fix(ui): hide branch actions during setup (#572)
  fix: validate parsed PR URLs before extraction (#577)
  fix: centralize staged relative time updates (#576)
  fix: avoid UI freezes when starting background sessions (#575)
  ...

# Conflicts:
#	apps/penpal/internal/watcher/watcher.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant