#2687 · Plugin discovery timeout message
Verdict: NOT REPRODUCED · Root-cause confidence: high
1. TL;DR
The CLI prints the reported statement only after its read-only plugin discovery request times out. The caller then exits before it sends the plugin command request. Two clean tests recorded three discovery GET requests and no command POST request. Therefore, the statement about command execution is accurate for this main-branch path. The historical duplicate writes need another cause.
The issue content was untrusted data. This investigation did not run an issue script, patch, branch, attachment, or external link.
2. Claims vs findings
| Claim | Status | Evidence |
|---|---|---|
| The CLI can print the statement after a response timeout. | Verified | Both tests produced an unreachable result after three timed-out discovery requests. |
| The client cannot know whether the plugin command ran on this path. | Refuted on main | The caller exits at the failed discovery step. It cannot reach the later command POST. |
| A retry of this exact path can repeat a write. | Not reproduced | Both tests recorded three GET requests and zero POST requests. |
| The reported historical duplicate writes came from this path. | Unverified | The historical process and server request logs were not available. |
3. Environment
- Trusted commit:
8d926c312569b63924825db761e9cc73663bc3bc. - Source package version: bb-app 0.40.0.
- Linux 7.0.0-30-generic x86_64, Node.js v24.18.0, pnpm 9.15.0.
- Each test used an OS-assigned temporary loopback port.
- No bb process, provider, account, persistent port, or bb data directory was used.
4. Minimal reproduction
- Install and build the trusted checkout.
pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build
- Copy the reproduction test into
apps/cli/src/__tests__/. - Run the focused test.
pnpm exec turbo run test --filter=@bb/cli -- src/__tests__/issue-2687-repro.test.ts
Expected if the defect exists: the server records a plugin command POST before the message appears.
Actual first run:
✓ src/__tests__/issue-2687-repro.test.ts (1 test) 112ms Test Files 1 passed (1) Tests 1 passed (1) Recorded requests: GET /api/v1/plugins/contributions GET /api/v1/plugins/contributions GET /api/v1/plugins/contributions Recorded command POST requests: 0
Reproduction test source
import { createServer } from "node:http";
import type { AddressInfo } from "node:net";
import { describe, expect, it } from "vitest";
import {
describeUnreachableServer,
fetchPluginCliContributions,
} from "../plugin-cli-proxy.js";
describe("plugin command discovery timeout", () => {
it("does not send a plugin command request", async () => {
const requests: Array<{
method: string | undefined;
url: string | undefined;
}> = [];
const server = createServer((request) => {
requests.push({ method: request.method, url: request.url });
});
await new Promise<void>((resolve) => {
server.listen(0, "127.0.0.1", resolve);
});
const { port } = server.address() as AddressInfo;
const baseUrl = `http://127.0.0.1:${port}`;
try {
const result = await fetchPluginCliContributions(baseUrl, 20, {
sleep: async () => undefined,
});
expect(result.outcome).toBe("unreachable");
if (result.outcome !== "unreachable") return;
expect(
describeUnreachableServer(
baseUrl,
result.cause,
result.lastTimeoutMs,
result.attempts,
),
).toContain("your command did not run");
expect(requests).toEqual([
{ method: "GET", url: "/api/v1/plugins/contributions" },
{ method: "GET", url: "/api/v1/plugins/contributions" },
{ method: "GET", url: "/api/v1/plugins/contributions" },
]);
expect(requests.some((request) => request.url?.endsWith("/cli"))).toBe(
false,
);
} finally {
server.closeAllConnections();
await new Promise<void>((resolve, reject) => {
server.close((error) => {
if (error) reject(error);
else resolve();
});
});
}
});
});
Verification
A second clean checkout used the same trusted commit. It used a new package install and a new temporary port. The same focused test passed in 114ms. It again recorded three discovery GET requests and no command POST request. The second run required no report correction.
5. Root cause
The message formatter alone receives only the connection result. However, the caller supplies a stronger system guarantee. The caller first waits for plugin discovery and exits on an unreachable result.
The failed requests are GET requests to the contribution endpoint. They do not run a plugin command.
The caller can invoke the plugin command only after successful discovery. That later function sends the separate command POST.
The main-branch control flow makes the command-state statement knowable. The historical duplicates did not originate from this exact failure path.
6. Proposed fix
No source change is supported by the direct result. A later investigation should match each historical CLI process to server request logs. That evidence can identify the request path that produced duplicate writes.
7. Related issues
Issue #2654 covers the same command-state claim. Its direct report also found no command POST on this timeout path.
8. Appendix
Commands used:
git fetch origin main git rev-parse origin/main pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build pnpm exec turbo run test --filter=@bb/cli -- src/__tests__/issue-2687-repro.test.ts git log -S'your command did not run' -- apps/cli/src/plugin-cli-proxy.ts git blame -L 128,149 -- apps/cli/src/plugin-cli-proxy.ts
The same agent ran the test in two separate clean checkouts. No development server or user data was necessary.