From 1ed12cd3bad3448ffc2da0151dec2748b43294b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Thu, 16 Jul 2026 00:38:12 +0000 Subject: [PATCH] resolve a relative task cwd against the user's home before spawning the file browser sends msg.cwd relative to the user's home and it went straight to Bun.spawn, which resolves it against the server's cwd. when that directory does not exist posix_spawn reports ENOENT naming the binary rather than the directory, so "Convert Audio" failed with the misleading "posix_spawn 'bash'". Co-Authored-By: Claude Opus 4.8 --- TODO.md | 7 ------- src/servers/api/tasks/task-executor.ts | 7 ++++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/TODO.md b/TODO.md index 6eb04149..c89e8c29 100644 --- a/TODO.md +++ b/TODO.md @@ -27,13 +27,6 @@ Deferred work. Context: Officer is collapsing from multi-tenant / open-source-re ## Known bugs -- [ ] **Convert Audio task fails with `ENOENT: posix_spawn 'bash'`.** Misleading error — the real - cause is a *relative* `cwd` passed to `Bun.spawn` (ENOENT fires when the child's cwd doesn't - exist, not when the binary is missing). Fix is in `api/tasks/task-executor.ts`: resolve - `msg.cwd` against the user's home when it isn't absolute - (`isAbsolute(msg.cwd) ? msg.cwd : join(homeDir, msg.cwd)`). Was written and verified once, then - discarded in a working-tree cleanup. - - [ ] **`bootstrap.ts` runs `npm install -g` for Pi on every boot.** `findPiPackageDir` checks stale paths and an outdated package name, so `installPi` always fires and floods the logs with `EEXIST` noise. Should detect `@earendil-works/pi-coding-agent` at the real npm prefix. diff --git a/src/servers/api/tasks/task-executor.ts b/src/servers/api/tasks/task-executor.ts index 323e895e..357a10c8 100644 --- a/src/servers/api/tasks/task-executor.ts +++ b/src/servers/api/tasks/task-executor.ts @@ -1,5 +1,5 @@ import type { ServerWebSocket } from 'bun'; -import { join } from 'node:path'; +import { join, isAbsolute } from 'node:path'; import { mkdirSync, writeFileSync, chmodSync, rmSync } from 'node:fs'; import { getTaskByDirName } from 'officerdb'; import { getHomeDirForRole, DATA_PATH } from '../../data-path'; @@ -124,9 +124,10 @@ async function handleRun(ws: ServerWebSocket, msg: RunMessage) { const runner = getRunner(language); const cmd = [...runner, scriptPath, ...positionalArgs]; - // Resolve cwd + // msg.cwd arrives from the file browser relative to the user's home; Bun.spawn needs it absolute + // (a missing cwd surfaces as ENOENT naming the binary, not the directory) const homeDir = getHomeDirForRole(email, role); - const cwd = msg.cwd ?? homeDir; + const cwd = msg.cwd ? (isAbsolute(msg.cwd) ? msg.cwd : join(homeDir, msg.cwd)) : homeDir; let spawnCmd: string[]; let spawnEnv: Record;