An adapter exit 127 now names the program that wasn't found (#1873, lane r127).
Jason hit "The assistant couldn't reply. Details: adapter exited 127" on the dev instance. Cause: the Console there ran without MOSAIC_CLAUDE_BIN, so a claude-code session ran /usr/bin/claude, a wrapper that execs /opt/claude-code/bin/claude. The sandbox binds /usr and not /opt, so the exec failed and the shell exited 127. The dev deploy script now sets MOSAIC_CLAUDE_BIN (outside the repo).
This change makes the message say what was missing. On exit 127 the runner reads the last 16 KiB of the turn's stderr and, when a shell or env printed its own not-found line, the reason becomes adapter exited 127 (command not found: claude). It returns a basename only, never a host path, and refuses names that look like a key. Other exit codes are unchanged.
Tests: four new tests in packages/harness/tests/runner.test.mjs, red before the fix (0/3, then 2/2 on the review round). Lane gate 14 files, 274/0. Lead check at 387f73a7a: 16 files that import runner.mjs or mention the text, 285/0.
Reviews (fresh Opus 5.5 delegates): review approved with 6 P3, five fixed in 387f73a7a. Re-check approved with 4 P3, left as follow-ups.
Follow-ups:
A launch refused at start writes nothing to the thread, so the person waits with no reply.
claude-code preflight checks the binary on the host, not inside the sandbox. A claude outside /usr with MOSAIC_CLAUDE_BIN unset fails with a bare "adapter exited 254".
A short key-shaped token, or a bash redirect to a missing file, can still be named as the program.
An adapter exit 127 now names the program that wasn't found (#1873, lane r127).
Jason hit "The assistant couldn't reply. Details: adapter exited 127" on the dev instance. Cause: the Console there ran without `MOSAIC_CLAUDE_BIN`, so a claude-code session ran `/usr/bin/claude`, a wrapper that execs `/opt/claude-code/bin/claude`. The sandbox binds /usr and not /opt, so the exec failed and the shell exited 127. The dev deploy script now sets `MOSAIC_CLAUDE_BIN` (outside the repo).
This change makes the message say what was missing. On exit 127 the runner reads the last 16 KiB of the turn's stderr and, when a shell or env printed its own not-found line, the reason becomes `adapter exited 127 (command not found: claude)`. It returns a basename only, never a host path, and refuses names that look like a key. Other exit codes are unchanged.
Tests: four new tests in `packages/harness/tests/runner.test.mjs`, red before the fix (0/3, then 2/2 on the review round). Lane gate 14 files, 274/0. Lead check at 387f73a7a: 16 files that import runner.mjs or mention the text, 285/0.
Reviews (fresh Opus 5.5 delegates): review approved with 6 P3, five fixed in 387f73a7a. Re-check approved with 4 P3, left as follow-ups.
Follow-ups:
- A launch refused at start writes nothing to the thread, so the person waits with no reply.
- claude-code preflight checks the binary on the host, not inside the sandbox. A `claude` outside /usr with `MOSAIC_CLAUDE_BIN` unset fails with a bare "adapter exited 254".
- A short key-shaped token, or a bash redirect to a missing file, can still be named as the program.
A claude-code turn on a Console started without MOSAIC_CLAUDE_BIN failed
with a bare "adapter exited 127". The sandbox binds /usr, so the wrapper
/usr/bin/claude is visible, but its exec target /opt/claude-code/bin/claude
isn't bound, and the shell exits 127.
On exit 127 the runner now reads the tail of the turn's stderr, finds the
shell's "not found" line (bash, dash, env) and adds the program's basename:
"adapter exited 127 (command not found: claude)". It never shows a host
path or anything that isn't a plain program name; a 127 without such a
line keeps the bare reason.
The deploy side (MOSAIC_CLAUDE_BIN on the Console unit) is a Lead-owned
script change, written up in the lane report.
Review P3-1: a "No such file or directory" line from another program
(cat, ls) no longer counts. Only bash's "line N:", dash's "N:" and env's
quoted form do.
P3-2: a name with a run of 16 letters and digits looks like a key, so it
stays in the run's private stderr instead of the reply.
P3-3: a 16 KiB stderr window that starts mid-file drops its partial first
line, so a cut name ("aude") isn't reported.
P3-4: CRLF lines read the same as LF lines.
P3-5: tests for the name check (tokens without spaces, key-shaped names),
for a cat line, and for the window boundary through the runner.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
An adapter exit 127 now names the program that wasn't found (#1873, lane r127).
Jason hit "The assistant couldn't reply. Details: adapter exited 127" on the dev instance. Cause: the Console there ran without
MOSAIC_CLAUDE_BIN, so a claude-code session ran/usr/bin/claude, a wrapper that execs/opt/claude-code/bin/claude. The sandbox binds /usr and not /opt, so the exec failed and the shell exited 127. The dev deploy script now setsMOSAIC_CLAUDE_BIN(outside the repo).This change makes the message say what was missing. On exit 127 the runner reads the last 16 KiB of the turn's stderr and, when a shell or env printed its own not-found line, the reason becomes
adapter exited 127 (command not found: claude). It returns a basename only, never a host path, and refuses names that look like a key. Other exit codes are unchanged.Tests: four new tests in
packages/harness/tests/runner.test.mjs, red before the fix (0/3, then 2/2 on the review round). Lane gate 14 files, 274/0. Lead check at387f73a7a: 16 files that import runner.mjs or mention the text, 285/0.Reviews (fresh Opus 5.5 delegates): review approved with 6 P3, five fixed in
387f73a7a. Re-check approved with 4 P3, left as follow-ups.Follow-ups:
claudeoutside /usr withMOSAIC_CLAUDE_BINunset fails with a bare "adapter exited 254".Review P3-1: a "No such file or directory" line from another program (cat, ls) no longer counts. Only bash's "line N:", dash's "N:" and env's quoted form do. P3-2: a name with a run of 16 letters and digits looks like a key, so it stays in the run's private stderr instead of the reply. P3-3: a 16 KiB stderr window that starts mid-file drops its partial first line, so a cut name ("aude") isn't reported. P3-4: CRLF lines read the same as LF lines. P3-5: tests for the name check (tokens without spaces, key-shaped names), for a cat line, and for the window boundary through the runner.