#2382 · bb status exits 0 against a dead daemon and hangs with zero bytes against a stalled one
Verdict: REPRODUCED · Root-cause confidence: high
1. TL;DR
bb status exits with code 0 when the configured server port refuses the connection.
The command then prints a project ID from the local environment as valid context.
A server that accepts a request but sends no response makes bb status and bb plugin list stay silent.
The CLI gives the SDK a raw fetch function, so the CLI skips the SDK request limit.
The status code also converts connection errors to empty results and never reports the unavailable server.
2. Claims vs findings
| Claim from the issue | Status | Evidence |
|---|---|---|
bb status returns code 0 against a closed port. |
Verified | Version 0.40.0 returned code 0 in 166 ms. It printed Project: proj_xxxxxxxxxx. |
bb status stays silent when the server accepts the socket but sends no response. |
Verified | The 3-second test limit stopped the process. Both output streams had zero bytes. |
bb plugin list has the same silent wait. |
Verified | The 3-second test limit stopped the process. The server log recorded one GET /api/v1/plugins. |
| The plugin contribution probe uses three finite request periods. | Verified | The probe made three requests. It failed after 10.95 seconds and named the last 4000 ms period. |
| A plugin command stays silent after a successful probe if its dispatch request stalls. | Verified | The server answered the probe and held the dispatch request. The 3-second test limit found zero output bytes. |
No bb command has a finite request limit. |
Refuted | The plugin dispatch sets a 65-minute header limit. This limit is too long for a health check, but it is finite. |
| An answering server with invalid data gives the three errors in the issue table. | Unverified | This investigation did not repeat that secondary schema test. The exact errors can change with the response schema. |
Eight separate documents use bb status as a health check. |
Unverified | The repository has several context and inspection references. The issue did not include the eight source locations. |
3. Environment
- bb commit:
ad79bbb5ec909524f8f281e62d860c588a86f332. - bb CLI: 0.40.0.
- OS: Linux 7.0.0-30-generic, x86_64.
- Node: v24.18.0. Node ABI: 137. pnpm: 9.15.0.
- Build: Turbo reported 18 successful tasks.
- No provider or real bb instance took part in the test.
- The script selected one free server port. The recorded run used
127.0.0.1:39941. - The test did not start the bb app or the host daemon.
- The fake server did not use a data directory.
4. Minimal reproduction
Use Node 24.18.0 on Linux. Clone both repositories and build the exact bb commit:
mkdir bb-2382-repro cd bb-2382-repro git clone https://github.com/get-bb/reports.git reports git clone https://github.com/get-bb/bb.git bb git -C bb checkout ad79bbb5ec909524f8f281e62d860c588a86f332 cd bb corepack pnpm install --frozen-lockfile --prefer-offline --package-import-method=copy corepack pnpm exec turbo run build cd ../reports
The working directory must now be the reports repository. Run the supplied script:
chmod +x issues/2382/repro/run-repro.sh issues/2382/repro/run-repro.sh ../bb
The script selects a free port and starts a local fake server. It does not use a bb data directory.
Actual output from the closed-port case:
$ BB_SERVER_URL=http://127.0.0.1:39941 BB_PROJECT_ID=proj_xxxxxxxxxx bb status Project: proj_xxxxxxxxxx Thread: (not set) exit=0
Expected output:
Error: Cannot connect to BB server. Ensure it is running and BB_SERVER_URL is correct. exit=1
Actual output from the stalled cases:
status exit=124 stdout_bytes=0 stderr_bytes=0 plugin-list exit=124 stdout_bytes=0 stderr_bytes=0 plugin-probe exit=1 stdout_bytes=0 stderr_bytes=203 plugin-command exit=124 stdout_bytes=0 stderr_bytes=0
The plugin probe produced this message after 10.95 seconds:
bb did not respond at http://127.0.0.1:39941 after 3 attempts (last window 4000ms) — it may be busy or temporarily unreachable. No server response was received and your command did not run; re-run it.
The server log confirms the request paths:
GET /api/v1/system/config GET /api/v1/plugins GET /api/v1/plugins/contributions GET /api/v1/plugins/contributions GET /api/v1/plugins/contributions
The expected-behavior test fails on the base commit:
✖ bb status fails when the server port is closed AssertionError [ERR_ASSERTION]: The command reported success. actual: 0 expected: 0 operator: notStrictEqual
Repro files:
- run-repro.sh
- fake-server.mjs
- status-dead.test.mjs
- status-dead.test.log
- stall-results.txt
- server-stall-all.log
- server-dispatch-stall.log
- stalled-plugin-probe.stderr
- stalled-plugin-probe.time
5. Root cause
The defect has two parts.
5.1 The CLI skips the SDK request limit
The SDK has a 75-second request limit and adds an AbortSignal to each request.
See the default limit and the wrapper.
The Node SDK uses that wrapper only when the caller does not supply a fetch function.
The CLI always supplies cliFetch, which directly calls the platform fetch function.
See the CLI client.
This one choice removes the SDK limit from 151 CLI SDK call sites, including bb plugin list.
bb status also calls the same raw fetch function before its SDK calls.
See the system configuration request.
5.2 The status command hides connection errors
The system configuration request catches every error and leaves serverAvailable false.
The status SDK also converts each project or thread request error to null.
See the error conversion and its use.
The command then prints the environment project ID when the server did not return a project.
See the output branch.
No final check turns serverAvailable === false into a failure.
5.3 The corrected plugin claim
The issue comment says that plugin dispatch has no limit. The base commit has a 65-minute header limit.
This limit still permits a long silent wait. It does not cause the two built-in command defects.
No relevant file changed between the base commit and origin/main at commit b629714e31487bde8af5574639422a9b5c97cbb5.
6. Proposed fix (first principles)
- Stop supplying the raw
cliFetchfunction tocreateNodeBbSdk. - Let the Node SDK apply its request limit to normal CLI SDK calls.
- Use a named raw fetch function only for plugin dispatch, which needs its separate 65-minute limit.
- Apply a short request limit to the direct status and plugin route calls.
- Make the first successful status response prove server availability, even when
dataDiris absent. - Return code 1 when no status request receives a server response.
- Add process tests for a refused connection and a server that sends no headers.
A 75-second default is finite but too long for a health check. Give bb status a short, documented limit.
Do not change the host daemon protocol version. This fix changes only local CLI request policy.
7. Related issues
- PR #1313 added the finite plugin contribution probe.
- PR #1809 added the 65-minute plugin dispatch limit.
- Issue #1524 covered a similar desktop startup wait.
8. Appendix
Build commands
pnpm install --frozen-lockfile --prefer-offline --package-import-method=copy pnpm exec turbo run build
Investigation commands
gh issue view 2382 --comments
gh issue view 2382 --json number,title,body,state,labels,projectItems,comments,url,author,createdAt,updatedAt
rg -n "runPluginCliCommand|fetchPluginCliContributions|cliFetch" apps/cli packages/sdk
git blame -L 45,140 -- apps/cli/src/commands/status.ts
git log ad79bbb5ec909524f8f281e62d860c588a86f332..origin/main -- apps/cli/src/commands/status.ts apps/cli/src/client.ts apps/cli/src/plugin-cli-proxy.ts packages/sdk/src
rg -n 'createCliBbSdk\(' apps/cli/src --glob '*.ts' --glob '!**/__tests__/**'
cd ../reports
issues/2382/repro/run-repro.sh ../bb
Raw evidence
The repro directory contains all process output, server request logs, and elapsed time data.
Verification
The verifier first found that the old commands used the wrong working directory. It also found a fixed-port risk and an incorrect call-site count.
The revised harness ran from the reports repository against a built bb checkout. It selected a free port and reproduced every stated result.
The report now gives clone steps for both repositories, states the actual resources, and reports 151 SDK call sites.