Repository navigation
Description
Summary
After the server moved to a nightly with a newer daemon protocol (237 → 246), a Mac machine stayed disconnected. Its auto-updating LaunchAgent daemon downloaded and installed the server's bb-app, but the install command exited 127, so bb recorded a failed update, never restarted into the new build, and kept retrying with backoff. The npm beside a node installed by an older mise is a bash wrapper that runs mise reshim after every global install, and mise is not on the LaunchAgent's PATH. Expected: the daemon restarts on the server's protocol, as it does with a plain node install.
Versions and environment
- Server: bb-app
0.46.2-nightly.39620384282.1, npm install run by a systemd user unit (server moved here withbb server move), Debian 13, Node 24.17.0 from mise. - Affected machine: macOS (version not recorded), bb-app 0.46.1 daemon run by the LaunchAgent
app.getbb.host-daemon.<slug>that the desktop app installed withinstall-machine.sh --adoptafter the server move (--auto-update), Node 24.18.0 from mise (~/.local/share/mise/installs/node/24.18.0/bin/nodeinProgramArguments), bb Connect. - Repro machine: Debian 13 (trixie), mise 2026.9.13 with its binary in
~/.local/bin, bbmainat 2799d45.
Steps to reproduce
Smallest repro: a global install through the npm wrapper of a node that an older mise installed, with PATH built the way defaultInstallTarball builds it (node's directory, then launchd's default PATH):
NODE_DIR=~/.local/share/mise/installs/node/24.17.0/bin
mkdir /tmp/mise-npm-prefix && cd /tmp
env -i HOME="$HOME" PATH="$NODE_DIR:/usr/bin:/bin:/usr/sbin:/sbin" \
"$NODE_DIR/npm" install -g --prefix /tmp/mise-npm-prefix bb-app@0.46.1
echo "exit=$?"Through bb's own code path, from a bb checkout at 2799d45 with dependencies installed:
pnpm exec turbo run generate:profile-worker --filter=@bb/process-utils
mkdir /tmp/bb-repro /tmp/bb-repro-dl /tmp/bb-repro-prefix-a /tmp/bb-repro-prefix-b
cat > /tmp/bb-repro/repro-self-update.mts <<EOF
import { defaultInstallTarball, defaultRunProcess } from "$PWD/apps/host-daemon/src/protocol-self-update.ts";
const tarball = process.argv[2];
if (tarball === undefined) throw new Error("usage: repro-self-update.mts <tarball>");
console.log("PATH:", process.env.PATH);
console.log("execPath:", process.execPath);
try {
await defaultInstallTarball(tarball, defaultRunProcess);
console.log("defaultInstallTarball: resolved");
} catch (error) {
const e = error as { code?: unknown; stdout?: string; stderr?: string };
console.log("defaultInstallTarball: rejected, code", e.code);
console.log("stdout:", JSON.stringify(e.stdout));
console.log("stderr:", JSON.stringify(e.stderr));
}
EOF
curl -fsS -o /tmp/bb-repro-dl/bb-app.tgz http://127.0.0.1:38886/install/bb-app.tgz
NODE=~/.local/share/mise/installs/node/24.17.0/bin/node
env -i HOME="$HOME" PATH=/usr/bin:/bin:/usr/sbin:/sbin BB_APP_NPM_PREFIX=/tmp/bb-repro-prefix-a \
"$NODE" --import tsx /tmp/bb-repro/repro-self-update.mts /tmp/bb-repro-dl/bb-app.tgz
env -i HOME="$HOME" PATH="$HOME/.local/bin:/usr/bin:/bin:/usr/sbin:/sbin" BB_APP_NPM_PREFIX=/tmp/bb-repro-prefix-b \
"$NODE" --import tsx /tmp/bb-repro/repro-self-update.mts /tmp/bb-repro-dl/bb-app.tgzDoes not reproduce:
- with mise's directory on PATH (second run above);
- with the wrapper mise wrote for node 22.19.0 on 2026-10-21, which runs
mise reshim || true(line 101, "Run mise reshim, ignore its exit code"): the same smallest repro printsmise: command not foundand exits 0. The wrapper written for 24.17.0 on 2026-06-21 runs a baremise reshim(line 76) underset -euo pipefail.
Expected vs actual
Smallest repro, 24.17.0 wrapper (the package is installed; lib/node_modules/bb-app/package.json reports 0.46.1):
added 52 packages in 2s
24 packages are looking for funding
run `npm fund` for details
Reshimming mise 24.17.0...
/home/<user>/.local/share/mise/installs/node/24.17.0/bin/npm: line 76: mise: command not found
exit=127
bb code path, launchd PATH:
PATH: /usr/bin:/bin:/usr/sbin:/sbin
execPath: /home/<user>/.local/share/mise/installs/node/24.17.0/bin/node
defaultInstallTarball: rejected, code 127
stdout: "\nadded 46 packages in 2s\n\n8 packages are looking for funding\n run `npm fund` for details\n"
stderr: "npm warn Unknown cli config \"--allow-scripts\". This will stop working in the next major version of npm.\nReshimming mise 24.17.0...\n/home/<user>/.local/share/mise/installs/node/24.17.0/bin/npm: line 76: mise: command not found\n"
bb code path, mise on PATH:
PATH: /home/<user>/.local/bin:/usr/bin:/bin:/usr/sbin:/sbin
execPath: /home/<user>/.local/share/mise/installs/node/24.17.0/bin/node
defaultInstallTarball: resolved
Affected Mac, ~/.bb/logs/host-daemon*.log (stack trimmed):
{"level":50,"time":1792615491650,"component":"host-daemon","serverUrl":"https://<name>.getbb.app","err":{"type":"Error","message":"Command failed: npm install -g --allow-scripts=better-sqlite3,node-pty,@parcel/watcher --prefix /Users/<user>/.bb/npm /Users/<user>/.bb/bb-app-update-1087.tgz\nReshimming mise 24.18.0...\n/Users/<user>/.local/share/mise/installs/node/24.18.0/bin/npm: line 75: mise: command not found\n",…,"code":127,"killed":false,"signal":null,…,"stdout":"\nchanged 46 packages in 2s\n\n8 packages are looking for funding\n run `npm fund` for details\n",…},"msg":"Daemon self-update failed; keeping the current daemon running and retrying normally."}
{"level":40,"time":1792615502581,"component":"host-daemon","serverUrl":"https://<name>.getbb.app","attemptCount":6,"retryAt":1792615648964,"retryDelayMs":160000,"serverProtocolVersion":246,"msg":"Daemon self-update is backing off; keeping the current daemon running."}
Expected: defaultInstallTarball resolves once the package is installed, the daemon restarts, and the machine reconnects on protocol 246.
Evidence
defaultInstallTarballprependsdirname(process.execPath)to the inherited PATH and runs thenpmit finds there, which is the mise wrapper:bb/apps/host-daemon/src/protocol-self-update.ts
Lines 167 to 191 in 2799d45
export async function defaultInstallTarball( tarballPath: string, runProcess: SelfUpdateProcessRunner, ): Promise<void> { const executableDirectory = dirname(process.execPath); const inheritedPath = process.env.PATH; const path = inheritedPath ? `${executableDirectory}${delimiter}${inheritedPath}` : executableDirectory; const rawConfiguredPrefix = process.env.BB_APP_NPM_PREFIX?.trim(); const configuredPrefix = rawConfiguredPrefix === "" ? undefined : rawConfiguredPrefix; if (configuredPrefix !== undefined && !isAbsolute(configuredPrefix)) { throw new Error("BB_APP_NPM_PREFIX must be an absolute path"); } const prefixArgs = configuredPrefix === undefined ? [] : ["--prefix", configuredPrefix]; await runProcess( "npm", ["install", "-g", BB_APP_ALLOW_SCRIPTS_ARG, ...prefixArgs, tarballPath], { env: { ...process.env, PATH: path }, }, ); } - Only an
"updated"result restarts the daemon:bb/apps/host-daemon/src/server-connection.ts
Lines 395 to 406 in 2799d45
if ( error instanceof ServerResponseError && error.code === "protocol_version_mismatch" ) { this.protocolMismatchObserved = true; const result = await this.options.protocolSelfUpdater?.handleProtocolMismatch({ force: error.protocolUpdateRetryRequested, }); if (result === "updated") { await this.options.onSelfUpdateInstalled?.(); } - The LaunchAgent and the systemd unit set no PATH, only
BB_APP_NPM_PREFIXandBB_DATA_DIR:andbb/apps/server/src/assets/install-machine.sh
Lines 1079 to 1094 in 2799d45
<key>ProgramArguments</key> <array> <string>$escaped_node_bin</string> <string>$escaped_bb_app</string> <string>host-daemon</string> <string>--auto-update</string> <string>--host-daemon-port</string> <string>$host_daemon_port</string> <string>--server-url</string> <string>$escaped_server</string> </array> <key>EnvironmentVariables</key> <dict> <key>BB_APP_NPM_PREFIX</key><string>$escaped_bb_app_npm_prefix</string> <key>BB_DATA_DIR</key><string>$escaped_data_dir</string> </dict> bb/apps/server/src/assets/install-machine.sh
Lines 1162 to 1164 in 2799d45
ExecStart="$escaped_node_bin" "$escaped_bb_app" host-daemon --auto-update --host-daemon-port "$host_daemon_port" --server-url "$escaped_server" Environment="BB_APP_NPM_PREFIX=$escaped_bb_app_npm_prefix" Environment="BB_DATA_DIR=$escaped_data_dir" - The server's in-app updater is unaffected: its
npm installis not global, and the wrapper passes non-global commands straight tonpm-cli.js. It can also already runnpm-cli.jswithprocess.execPath:bb/packages/bb-app/src/app-update/npm-revision.ts
Lines 154 to 169 in 2799d45
const npmCommand = args.npmCliPath === null ? { args: [] as string[], command: "npm" } : { args: [args.npmCliPath], command: process.execPath }; try { args.signal?.throwIfAborted(); args.onStep(`Downloading bb-app ${args.version}`); await runCheckedCommand(args.runner, "npm install", { args: [ ...npmCommand.args, "install", "--no-audit", "--no-fund", "--omit=dev", `bb-app@${args.version}`, ], - Server side during the outage:
Rejecting daemon session: protocol version mismatch. An older auto-update-enabled daemon will install this server's bb-app; …for the Mac host 32 times in 6 minutes, about every 11 s.bb machine retry-updatedid not change the outcome. - Found from bb thread
thr_gme2wi3yrbon the server machine.
What you ruled out
- Not LaunchAgent server has no node on PATH, so the MCP server (and other plugins) can't run the bb CLI #5807: that is the MCP plugin choosing the node-shebang
BB_CLI. Both come from the LaunchAgent having no PATH, but aBB_CLI_LAUNCHERfix does not reach this code path. Related PATH trackers: Packaged Nightly plugin processes lose PATH for node and gh #2343, Host daemon falls back to bare launchd PATH when login-shell probe fails, breaking provider CLI detection (codex/claude) until daemon restart #5292. - Not transport, auth, or the artifact: the server URL is https, the download and install succeed (
changed 46 packages), and the same version installed from an interactive shell (mise on PATH) followed bylaunchctl kickstart -kreconnected the machine on protocol 246. - Not auto-update being off: the daemon ran the update and logged
Daemon self-update failed. protocol-self-update.tsis identical between 0.46.1 (411eac5) andmain(2799d45).
Possible fixes: run npm's JS entry with process.execPath instead of the npm on PATH (the in-app updater already has resolveNpmCliPath), or treat a verified installed package as success when only a post-install step failed, or write a PATH into the generated LaunchAgent and systemd unit (that would also help #5807).
Suggested priority and effort (optional)
Low to medium. It affects every auto-updating machine whose node came from an older mise and whose mise binary is not on the service PATH, and on nightly the daemon protocol changes often (237 → 246 between 0.46.1 and this nightly). Workaround: install the server's version by hand and run launchctl kickstart -k, or add EnvironmentVariables:PATH with mise's directory to the plist and reload it. No data is lost, but the machine is unusable until someone intervenes.
Checks
- I reproduced this on the latest release or on
main, or I say above that I could not. - I searched open and closed issues for the same problem.
- If an agent wrote this, the body ends with
> AGENT GENERATEDand links the thread or report.
AGENT GENERATED — written by Claude Code from bb thread thr_gme2wi3yrb on the server machine.
Activity
bb-slop-cop commentedon Oct 21, 2026
🚨 SLOP COP 🚨 ·
new-issue-autopilothost.confirmed-repro. Repeated the reproduction in a second clean trusted-main checkout.One host toolchain for executable discovery, child PATH, and proxy/CA…