From 1f49436d8ad0a1b53647275bd3314a9de7ee881f Mon Sep 17 00:00:00 2001 From: David Kaya Date: Wed, 15 Apr 2026 08:42:55 +0200 Subject: [PATCH] fix: serialize sidecar cleanup in batch delete to avoid requestId collision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple concurrent sidecar.deleteSession() calls used requestId: delete-session-\ which collides when two fire in the same millisecond. The second overwrites the first in the pending map, causing the first promise to never resolve and Promise.allSettled to hang indefinitely — producing Electron's 'reply was never sent' error. Run cleanup sequentially instead. Also add .catch() to rm() calls for robustness. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/main/AryxAppService.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/AryxAppService.ts b/src/main/AryxAppService.ts index 945fa71..02875b0 100644 --- a/src/main/AryxAppService.ts +++ b/src/main/AryxAppService.ts @@ -1166,23 +1166,23 @@ export class AryxAppService extends EventEmitter { const workspace = await this.loadWorkspace(); const idsToDelete = new Set(sessionIds); - // Collect cleanup work before mutating the array - const cleanupTasks: Promise[] = []; + // Run cleanup sequentially to avoid requestId collisions in sidecar dispatch for (const session of workspace.sessions) { if (!idsToDelete.has(session.id)) continue; const scratchpadDirectory = this.resolveScratchpadSessionDirectory(session); if (scratchpadDirectory) { - cleanupTasks.push(rm(scratchpadDirectory, { recursive: true, force: true })); + await rm(scratchpadDirectory, { recursive: true, force: true }).catch(() => { + // Best-effort — directory may not exist or be locked + }); } - cleanupTasks.push( - this.sidecar.deleteSession(session.id).then(() => undefined).catch(() => { - // Best-effort — don't fail the deletion if SDK cleanup fails - }), - ); - } - await Promise.allSettled(cleanupTasks); + try { + await this.sidecar.deleteSession(session.id); + } catch { + // Best-effort — don't fail the deletion if SDK cleanup fails + } + } workspace.sessions = workspace.sessions.filter((s) => !idsToDelete.has(s.id));