← reports

#2382 · bb status exits 0 against a dead daemon and hangs with zero bytes against a stalled one

Bug Priority: Medium Effort: Unknown cli open on GitHub 2026-08-27 · base ad79bbb5ec909524f8f281e62d860c588a86f332

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 issueStatusEvidence
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

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:

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.

See the fallback selection.

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.

See the limit and dispatcher.

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)

  1. Stop supplying the raw cliFetch function to createNodeBbSdk.
  2. Let the Node SDK apply its request limit to normal CLI SDK calls.
  3. Use a named raw fetch function only for plugin dispatch, which needs its separate 65-minute limit.
  4. Apply a short request limit to the direct status and plugin route calls.
  5. Make the first successful status response prove server availability, even when dataDir is absent.
  6. Return code 1 when no status request receives a server response.
  7. 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

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.