From 8aa1833e2b7a33d92da79d022232974b772db29b Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Mon, 13 Apr 2026 14:55:59 +0700 Subject: [PATCH] fix(server): await git worktree creation before responding to client Move createAgentWorktree() from the fire-and-forget background function into handleCreatePaseoWorktreeRequest so the worktree directory exists on disk before the client receives the response and navigates. Fixes ENOENT race when the app queries checkout status on a path that hasn't been created yet. Setup commands (npm install, etc.) remain background. --- packages/server/src/server/session.ts | 9 +++--- .../server/src/server/worktree-session.ts | 28 +++++++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/packages/server/src/server/session.ts b/packages/server/src/server/session.ts index 944d708e5..bcbe0e340 100644 --- a/packages/server/src/server/session.ts +++ b/packages/server/src/server/session.ts @@ -173,7 +173,7 @@ import { ScheduleService } from "./schedule/service.js"; import { assertSafeGitRef as assertWorktreeSafeGitRef, buildAgentSessionConfig as buildWorktreeAgentSessionConfig, - createPaseoWorktreeInBackground as createWorktreeInBackgroundSession, + runWorktreeSetupInBackground as runWorktreeSetupInBackgroundSession, handleCreatePaseoWorktreeRequest as handleCreateWorktreeRequest, handlePaseoWorktreeArchiveRequest as handleWorktreeArchiveRequest, handlePaseoWorktreeListRequest as handleWorktreeListRequest, @@ -6157,20 +6157,19 @@ export class Session { registerPendingWorktreeWorkspace: (options) => this.registerPendingWorktreeWorkspace(options), sessionLogger: this.sessionLogger, - createPaseoWorktreeInBackground: (options) => this.createPaseoWorktreeInBackground(options), + runWorktreeSetupInBackground: (options) => this.runWorktreeSetupInBackground(options), }, request, ); } - private async createPaseoWorktreeInBackground(options: { + private async runWorktreeSetupInBackground(options: { requestCwd: string; repoRoot: string; - baseBranch: string; slug: string; worktreePath: string; }): Promise { - return createWorktreeInBackgroundSession( + return runWorktreeSetupInBackgroundSession( { paseoHome: this.paseoHome, emitWorkspaceUpdateForCwd: (cwd) => this.emitWorkspaceUpdateForCwd(cwd), diff --git a/packages/server/src/server/worktree-session.ts b/packages/server/src/server/worktree-session.ts index 637a95f4c..3ce9af075 100644 --- a/packages/server/src/server/worktree-session.ts +++ b/packages/server/src/server/worktree-session.ts @@ -109,10 +109,9 @@ type HandleCreatePaseoWorktreeRequestDependencies = { branchName: string; }) => Promise; sessionLogger: Logger; - createPaseoWorktreeInBackground: (options: { + runWorktreeSetupInBackground: (options: { requestCwd: string; repoRoot: string; - baseBranch: string; slug: string; worktreePath: string; }) => Promise; @@ -575,6 +574,15 @@ export async function handleCreatePaseoWorktreeRequest( worktreePath, branchName: normalizedSlug, }); + + await createAgentWorktree({ + cwd: repoRoot, + branchName: normalizedSlug, + baseBranch, + worktreeSlug: normalizedSlug, + paseoHome: dependencies.paseoHome, + }); + const descriptor = await dependencies.describeWorkspaceRecord(workspace); dependencies.emit({ type: "create_paseo_worktree_response", @@ -586,10 +594,9 @@ export async function handleCreatePaseoWorktreeRequest( }, }); - void dependencies.createPaseoWorktreeInBackground({ + void dependencies.runWorktreeSetupInBackground({ requestCwd: request.cwd, repoRoot, - baseBranch, slug: normalizedSlug, worktreePath, }); @@ -611,12 +618,11 @@ export async function handleCreatePaseoWorktreeRequest( } } -export async function createPaseoWorktreeInBackground( +export async function runWorktreeSetupInBackground( dependencies: CreatePaseoWorktreeInBackgroundDependencies, options: { requestCwd: string; repoRoot: string; - baseBranch: string; slug: string; worktreePath: string; }, @@ -624,14 +630,6 @@ export async function createPaseoWorktreeInBackground( let setupTerminalId: string | null = null; try { - await createAgentWorktree({ - cwd: options.repoRoot, - branchName: options.slug, - baseBranch: options.baseBranch, - worktreeSlug: options.slug, - paseoHome: dependencies.paseoHome, - }); - const setupCommands = getWorktreeSetupCommands(options.worktreePath); if (setupCommands.length > 0 && dependencies.terminalManager) { const runtimeEnv = await resolveWorktreeRuntimeEnv({ @@ -667,7 +665,7 @@ export async function createPaseoWorktreeInBackground( worktreePath: options.worktreePath, setupTerminalId, }, - "Background worktree creation failed", + "Background worktree setup failed", ); } finally { await dependencies.emitWorkspaceUpdateForCwd(options.worktreePath);