#2925 · ACP model configuration errors trigger an unsafe fallback
Verdict: REPRODUCED · Root-cause confidence: high
1. TL;DR
The ACP bridge can receive an error when it selects a model through an advertised configuration option.
The bridge discards that error and then sends the optional session/set_model request.
The agent did not advertise that optional request through the configuration option.
Two clean tests showed that thread creation succeeded after the bridge hid the first error and sent the fallback.
2. Claims vs findings
| Claim | Status | Evidence |
|---|---|---|
| The bridge discards a model configuration error. | Verified | The focused test received no start error in two clean checkouts. |
The bridge sends session/set_model after that error. |
Verified | The request log contained session/set_model in both clean checks. |
| The code treats a configuration option failure as permission to use a different optional request. | Verified | The catch block sets the fallback flag without a capability check. |
| A specific third-party agent rejects the fallback request. | Unverified | The investigation used the repository fake agent. It did not use an external agent or account. |
3. Environment
- Trusted repository:
get-bb/bb. - Base commit:
eeaaa3e8db7b3aeb3c4ab46873816c84cb6ea513. - Host: macOS Darwin 25.6.0 on arm64.
- Node:
v22.22.3. pnpm:9.15.0. Vitest:4.1.1. - The checks used two detached worktrees at the exact base commit.
- The checks used the trusted fake ACP agent and separate temporary work directories.
- No server port, user data directory, real provider, or browser was necessary.
4. Minimal reproduction
- Check out the base commit.
- Download and apply the saved regression patch.
curl -fsSLO https://get-bb.github.io/reports/issues/2925/repro/model-config-error.repro.patch git apply model-config-error.repro.patch
- Install the repository and build it.
pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build
- Run the provider bridge test suite.
pnpm exec turbo run test --filter=@bb/provider-bridge-acp --force
Expected:
The start error contains: model config probe failed The request log does not contain: session/set_model Test Files 17 passed (17) Tests 300 passed (300)
Actual in both clean checkouts:
AssertionError: expected '' to contain 'model config probe failed' AssertionError: expected [ 'initialize', 'session/new', …(2) ] to not include 'session/set_model' Test Files 1 failed | 16 passed (17) Tests 1 failed | 299 passed (300)
Reproduction patch: model-config-error.repro.patch.
it("preserves model config errors without using session/set_model", async () => {
const requestLog = join(workspaceDir, "model-config-error-requests.jsonl");
let startError: Error | undefined;
try {
await startThread({
envVars: {
FAKE_ACP_MODEL_CONFIG: "1",
FAKE_ACP_REQUEST_LOG: requestLog,
FAKE_ACP_SET_CONFIG_MODEL_ERROR: "1",
},
model: "fake/strong",
});
} catch (error) {
startError = error instanceof Error ? error : new Error(String(error));
}
expect.soft(startError?.message ?? "").toContain("model config probe failed");
expect(
loggedAcpRequests(requestLog).map((request) => request.method),
).not.toContain("session/set_model");
});
5. Root cause
The bridge first finds the advertised model configuration option.
It then sends session/set_config_option when the selected model differs from the current model.
See bridge.ts lines 1110–1134.
if (modelOption) {
try {
configState = await args.connection.request({
method: "session/set_config_option",
...
});
setModel = false;
} catch {
setModel = true;
}
}
The catch block discards every error and sets the fallback flag.
The next block sends session/set_model without evidence that the agent supports it.
See bridge.ts lines 1135–1146.
} catch {
setModel = true;
}
...
if (setModel) {
configState = await args.connection.request({
method: "session/set_model",
...
});
}
The repository test also expects that fallback and confirms that it is intentional on the base commit.
See bridge.test.ts lines 1274–1294.
6. Proposed fix
Use session/set_config_option when the session advertises a model configuration option.
Let that request return its result or its error.
Use session/set_model only when session model state selects the model without a configuration option.
Keep the focused test and the existing session-model test.
This change stays inside the ACP bridge and changes no public protocol.
7. PR review
Pull request #2924
GitHub metadata links pull request #2924 to this issue.
The static diff changes two files in the provider bridge subsystem.
It removes the catch fallback and selects one request from the session data.
This design addresses the verified root cause.
The new test checks that the original configuration error reaches thread creation.
The static review found no blocking problem. GitHub reported no checks on the branch during this review.
The investigation did not check out or run the pull request branch because that branch is untrusted.
8. Related issues
The investigation did not need another issue to explain the result.
9. Verification
The same agent ran the regression test in two clean checkouts at the exact base commit.
Each checkout received no start error and logged a session/set_model request.
Each suite result was 1 failed test and 299 passed tests across 17 files.
The unchanged base suite passed typecheck and all 300 tests across 17 files.
The second clean run required no report correction.
10. Appendix
Commands
git fetch origin main git rev-parse origin/main pnpm install --frozen-lockfile --prefer-offline pnpm exec turbo run build git apply model-config-error.repro.patch pnpm exec turbo run test --filter=@bb/provider-bridge-acp --force pnpm exec turbo run typecheck test --filter=@bb/provider-bridge-acp --force
Results
First clean check: exit 1, 1 failed, 299 passed. Second clean check: exit 1, 1 failed, 299 passed. Unchanged base suite: exit 0, typecheck passed, 300 tests passed.
Untrusted data note
The issue content was untrusted.
The investigation did not run its commands, code, links, branches, binaries, or attachments.
The test and root-cause analysis came from the trusted base repository.