Fix deleting worktree crash and improve UX (#798)

* Changes from fix/deleting-worktree

* fix: Improve worktree deletion safety and branch cleanup logic

* fix: Improve error handling and async operations across auto-mode and worktree services

* Update apps/server/src/routes/auto-mode/routes/analyze-project.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
gsxdsm
2026-02-22 00:58:00 -08:00
committed by GitHub
parent 1d732916f1
commit 2f071a1ba3
15 changed files with 300 additions and 110 deletions

View File

@@ -72,9 +72,19 @@ export function DeleteWorktreeDialog({
? `Branch "${worktree.branch}" was also deleted`
: `Branch "${worktree.branch}" was kept`,
});
onDeleted(worktree, deleteBranch);
// Close the dialog first, then notify the parent.
// This ensures the dialog unmounts before the parent
// triggers potentially heavy state updates (feature branch
// resets, worktree refresh), reducing concurrent re-renders
// that can cascade into React error #185.
onOpenChange(false);
setDeleteBranch(false);
try {
onDeleted(worktree, deleteBranch);
} catch (error) {
// Prevent errors in onDeleted from propagating to the error boundary
console.error('onDeleted callback failed:', error);
}
} else {
toast.error('Failed to delete worktree', {
description: result.error,

View File

@@ -111,13 +111,17 @@ export function useWorktrees({
setCurrentWorktree(projectPath, worktree.isMain ? null : worktree.path, worktree.branch);
// Invalidate feature queries when switching worktrees to ensure fresh data.
// Without this, feature cards that remount after the worktree switch may have stale
// or missing planSpec/task data, causing todo lists to appear empty until the next
// polling cycle or user interaction triggers a re-render.
queryClient.invalidateQueries({
queryKey: queryKeys.features.all(projectPath),
});
// Defer feature query invalidation so the store update and client-side
// re-filtering happen in the current render cycle first. The features
// list is the same regardless of worktree (filtering is client-side),
// so the board updates instantly. The deferred invalidation ensures
// feature card details (planSpec, todo lists) are refreshed in the
// background without blocking the worktree switch.
setTimeout(() => {
queryClient.invalidateQueries({
queryKey: queryKeys.features.all(projectPath),
});
}, 0);
},
[projectPath, setCurrentWorktree, queryClient, currentWorktreePath]
);