#3607 · Maintenance reads the default Claude profile
Bug · Priority: Medium · Effort: Low · providers · provider-claude-code · 2026-09-13
GitHub issue · Base cf51227e1135309a3c9c0baf5630be1ca7ba2714
REPRODUCED · Root-cause confidence: high · confirmed-repro
1. TL;DR
Maintenance can report an expired account even when a configured profile contains current credentials. Both maintenance readers use fixed default-profile paths. The usage reader rejects those expired credentials before reaching HTTP, and account identity also comes from the default file. Actual maintenance exports reproduced the defect in two clean checkouts using synthetic filesystem fixtures.
2. Claims vs findings
| Claim | Finding | Evidence |
|---|---|---|
| Configured credentials are ignored | Verified | Usage and health return expired with a current custom profile. |
| Account email is read from the wrong profile | Verified | Both-current fixture returns default email. |
| Live account and shipped release exhibit the bug | Unverified | No real account or historical bundle was inspected. |
| An SDK resolver exists | Verified with qualification | The helper is private, not a directly reusable exported function. |
| Custom files should override macOS Keychain | Not established | Credential precedence needs a decision; dynamic reproduction covers the non-Keychain path. |
3. Environment
Darwin arm64; Node v22.22.3; pinned pnpm 9.15.0; Vitest 4.1.1. Tests set the isolated worker platform to Linux and restore it afterward. CLI discovery/version and HTTP are mocked. Each test creates and removes real temporary filesystem fixtures. No real credentials, provider binaries, BB runtime data, database, or ports were used. Full trusted-base build: 56 successful tasks.
The installed pnpm launcher was broken. A temporary launcher from corepack enable --install-directory <temporary-bin> pnpm was placed first on PATH; frozen install and build then succeeded. Published logs normalize local paths.
4. Minimal reproduction
- Run the checkout/install/build commands below.
- Save the inline test below into
plugins/provider-claude-code/src/bridge/. - Run the focused Turbo command. Exit 1 is expected on this buggy base.
git clone https://github.com/get-bb/bb.git bb-3607 cd bb-3607 git checkout --detach cf51227e1135309a3c9c0baf5630be1ca7ba2714 corepack pnpm install --frozen-lockfile --prefer-offline corepack pnpm exec turbo run build corepack pnpm exec turbo run test --filter=bb-plugin-provider-claude-code -- provider-maintenance.config-dir.test.ts
Expected: configured usage ok, health ready, configured email. Actual assertion excerpts:
- "status": "ok" + "status": "expired" - "accountEmail": "configured@example.invalid" - "status": "ready" + "accountEmail": "default@example.invalid" + "status": "expired" - "accountEmail": "configured@example.invalid" + "accountEmail": "default@example.invalid" Tests 3 failed | 1 passed (4)
The passing control clears the override and supplies current default credentials. This rules out a generally broken HTTP fixture or parser.
Full test
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, expect, it, vi } from "vitest";
const state = vi.hoisted(() => ({ home: "" }));
vi.mock("node:os", async (importOriginal) => ({
default: {
...(await importOriginal<typeof import("node:os")>()),
homedir: () => state.home,
},
}));
vi.mock("node:child_process", () => ({
execFile: () => { throw new Error("Subprocess access forbidden in reproduction"); },
}));
vi.mock("@get-bb/plugin-sdk/provider-bridge", async (importOriginal) => ({
...(await importOriginal<typeof import("@get-bb/plugin-sdk/provider-bridge")>()),
experimental_resolveExecutablePath: async () => "/synthetic/claude",
experimental_readCliVersion: async () => "synthetic",
}));
import { getClaudeProviderHealth, getClaudeProviderUsage } from "./provider-maintenance.js";
const originalPlatform = process.platform;
const credential = (expired: boolean) => JSON.stringify({
claudeAiOauth: { accessToken: "synthetic-fixture", expiresAt: expired ? 1 : 4102444800000 },
});
beforeEach(async () => {
state.home = await fs.mkdtemp(path.join(os.tmpdir(), "bb-3607-fixture-"));
Object.defineProperty(process, "platform", { configurable: true, value: "linux" });
const custom = path.join(state.home, "profile");
await fs.mkdir(custom);
await fs.mkdir(path.join(state.home, ".claude"));
await fs.writeFile(path.join(custom, ".credentials.json"), credential(false));
await fs.writeFile(path.join(custom, ".claude.json"), JSON.stringify({ oauthAccount: { emailAddress: "configured@example.invalid" } }));
await fs.writeFile(path.join(state.home, ".claude", ".credentials.json"), credential(true));
await fs.writeFile(path.join(state.home, ".claude.json"), JSON.stringify({ oauthAccount: { emailAddress: "default@example.invalid" } }));
vi.stubEnv("CLAUDE_CONFIG_DIR", custom);
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
ok: true, status: 200,
json: async () => ({ five_hour: { utilization: 12 }, seven_day: { utilization: 23 } }),
}));
});
afterEach(async () => {
Object.defineProperty(process, "platform", { configurable: true, value: originalPlatform });
vi.unstubAllEnvs();
vi.unstubAllGlobals();
await fs.rm(state.home, { recursive: true, force: true });
});
it("uses the configured profile for usage despite an expired default profile", async () => {
const result = await getClaudeProviderUsage();
expect(result).toMatchObject({ supported: true, usage: { status: "ok" } });
});
it("uses the configured profile for health despite an expired default profile", async () => {
const result = await getClaudeProviderHealth();
expect(result).toMatchObject({ supported: true, health: { status: "ready", accountEmail: "configured@example.invalid" } });
});
it("reads the configured account identity when both profiles have current credentials", async () => {
await fs.writeFile(path.join(state.home, ".claude", ".credentials.json"), credential(false));
const result = await getClaudeProviderUsage();
expect(result).toMatchObject({ usage: { status: "ok", accountEmail: "configured@example.invalid" } });
});
it("control: reports usage successfully from a current default profile", async () => {
vi.stubEnv("CLAUDE_CONFIG_DIR", "");
await fs.writeFile(path.join(state.home, ".claude", ".credentials.json"), credential(false));
const result = await getClaudeProviderUsage();
expect(result).toMatchObject({ usage: { status: "ok", accountEmail: "default@example.invalid" } });
});
5. Root cause
The readers construct fixed paths:
path.join(os.homedir(), ".claude", ".credentials.json") path.join(os.homedir(), ".claude.json")
Usage returns expired before HTTP. Health uses the same credential reader and expiry condition. Bridge dispatch invokes those exports. A current custom file therefore cannot correct the selected default profile.
The SDK directory resolver handles the override for plugin roots, but is private and unused by maintenance. The custom account-file layout is modeled by the fixture; vendor file-writing behavior was not tested with an installed Claude binary.
6. Proposed fix and automatic-fix decision
Align maintenance credential and identity selection with the intended configured profile. Preserve default behavior and cover missing/malformed custom files, blank/relative/tilde paths, and macOS Keychain precedence. No PR: selecting a different authentication credential source and deciding fallback precedence exceed the rule’s simple-fix limits. Production code was not modified.
7. Verification
The same agent repeated the test in a second clean clone at the identical full commit, with a separate dependency installation and fresh temporary fixture directories. Both checkouts were clean before adding only the test. The same Turbo command ran required upstream builds and the test. Both runs exited 1 with three matching failures and one passing control; no report correction was needed. This is a repeated reproduction, not an independent review.
8. Related issues and PRs
No linked open PR appeared in issue timeline metadata or the open-PR search for 3607. Nearby usage reports concern pooled-account display (#3243), context timing (#3220), and HTTP proxy support (#3239); none supplied reproduction code.
9. Appendix
Complete test assertion output from both runs is included below. Raw build evidence is retained locally; the full build passed 56 tasks.
Issue content was treated as untrusted claims. Suggested actions were not executed; the test was authored from trusted repository evidence. Live UI behavior, historical bundles, vendor-side login validity, and macOS Keychain behavior remain outside dynamic verification.
repro-first.log
bb-plugin-provider-claude-code:test: RUN v4.1.1 TEMP_CHECKOUT/base/plugins/provider-claude-code
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts (4 tests | 3 failed) 16ms
bb-plugin-provider-claude-code:test: × uses the configured profile for usage despite an expired default profile 8ms
bb-plugin-provider-claude-code:test: × uses the configured profile for health despite an expired default profile 3ms
bb-plugin-provider-claude-code:test: × reads the configured account identity when both profiles have current credentials 3ms
bb-plugin-provider-claude-code:test: ✓ control: reports usage successfully from a current default profile 2ms
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > uses the configured profile for usage despite an expired default profile
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, …(1) } to match object { supported: true, …(1) }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "supported": true,
bb-plugin-provider-claude-code:test: "usage": {
bb-plugin-provider-claude-code:test: - "status": "ok",
bb-plugin-provider-claude-code:test: + "status": "expired",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:55:18
bb-plugin-provider-claude-code:test: 53| it("uses the configured profile for usage despite an expired default p…
bb-plugin-provider-claude-code:test: 54| const result = await getClaudeProviderUsage();
bb-plugin-provider-claude-code:test: 55| expect(result).toMatchObject({ supported: true, usage: { status: "ok…
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 56| });
bb-plugin-provider-claude-code:test: 57|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > uses the configured profile for health despite an expired default profile
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, health: { …(9) } } to match object { supported: true, health: { …(2) } }
bb-plugin-provider-claude-code:test: (7 matching properties omitted from actual)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "health": {
bb-plugin-provider-claude-code:test: - "accountEmail": "configured@example.invalid",
bb-plugin-provider-claude-code:test: - "status": "ready",
bb-plugin-provider-claude-code:test: + "accountEmail": "default@example.invalid",
bb-plugin-provider-claude-code:test: + "status": "expired",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: "supported": true,
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:60:18
bb-plugin-provider-claude-code:test: 58| it("uses the configured profile for health despite an expired default …
bb-plugin-provider-claude-code:test: 59| const result = await getClaudeProviderHealth();
bb-plugin-provider-claude-code:test: 60| expect(result).toMatchObject({ supported: true, health: { status: "r…
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 61| });
bb-plugin-provider-claude-code:test: 62|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > reads the configured account identity when both profiles have current credentials
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, usage: { …(4) } } to match object { usage: { status: 'ok', …(1) } }
bb-plugin-provider-claude-code:test: (3 matching properties omitted from actual)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "usage": {
bb-plugin-provider-claude-code:test: - "accountEmail": "configured@example.invalid",
bb-plugin-provider-claude-code:test: + "accountEmail": "default@example.invalid",
bb-plugin-provider-claude-code:test: "status": "ok",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:66:18
bb-plugin-provider-claude-code:test: 64| await fs.writeFile(path.join(state.home, ".claude", ".credentials.js…
bb-plugin-provider-claude-code:test: 65| const result = await getClaudeProviderUsage();
bb-plugin-provider-claude-code:test: 66| expect(result).toMatchObject({ usage: { status: "ok", accountEmail: …
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 67| });
bb-plugin-provider-claude-code:test: 68|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: Test Files 1 failed (1)
bb-plugin-provider-claude-code:test: Tests 3 failed | 1 passed (4)
bb-plugin-provider-claude-code:test: Start at 07:36:44
bb-plugin-provider-claude-code:test: Duration 441ms (transform 226ms, setup 0ms, import 340ms, tests 16ms, environment 0ms)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ELIFECYCLE Test failed. See above for more details.
bb-plugin-provider-claude-code#test: ERROR command (TEMP_CHECKOUT/base/plugins/provider-claude-code) TEMP_CHECKOUT/bin/pnpm run test provider-maintenance.config-dir.test.ts exited (1)
Tasks: 4 successful, 5 total
Cached: 0 cached, 5 total
Time: 1.776s
Failed: bb-plugin-provider-claude-code#test
ERROR run failed: command exited (1)
repro-second.log
bb-plugin-provider-claude-code:test: RUN v4.1.1 TEMP_CHECKOUT/verify/plugins/provider-claude-code
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts (4 tests | 3 failed) 16ms
bb-plugin-provider-claude-code:test: × uses the configured profile for usage despite an expired default profile 8ms
bb-plugin-provider-claude-code:test: × uses the configured profile for health despite an expired default profile 3ms
bb-plugin-provider-claude-code:test: × reads the configured account identity when both profiles have current credentials 3ms
bb-plugin-provider-claude-code:test: ✓ control: reports usage successfully from a current default profile 2ms
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > uses the configured profile for usage despite an expired default profile
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, …(1) } to match object { supported: true, …(1) }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "supported": true,
bb-plugin-provider-claude-code:test: "usage": {
bb-plugin-provider-claude-code:test: - "status": "ok",
bb-plugin-provider-claude-code:test: + "status": "expired",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:55:18
bb-plugin-provider-claude-code:test: 53| it("uses the configured profile for usage despite an expired default p…
bb-plugin-provider-claude-code:test: 54| const result = await getClaudeProviderUsage();
bb-plugin-provider-claude-code:test: 55| expect(result).toMatchObject({ supported: true, usage: { status: "ok…
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 56| });
bb-plugin-provider-claude-code:test: 57|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > uses the configured profile for health despite an expired default profile
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, health: { …(9) } } to match object { supported: true, health: { …(2) } }
bb-plugin-provider-claude-code:test: (7 matching properties omitted from actual)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "health": {
bb-plugin-provider-claude-code:test: - "accountEmail": "configured@example.invalid",
bb-plugin-provider-claude-code:test: - "status": "ready",
bb-plugin-provider-claude-code:test: + "accountEmail": "default@example.invalid",
bb-plugin-provider-claude-code:test: + "status": "expired",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: "supported": true,
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:60:18
bb-plugin-provider-claude-code:test: 58| it("uses the configured profile for health despite an expired default …
bb-plugin-provider-claude-code:test: 59| const result = await getClaudeProviderHealth();
bb-plugin-provider-claude-code:test: 60| expect(result).toMatchObject({ supported: true, health: { status: "r…
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 61| });
bb-plugin-provider-claude-code:test: 62|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: FAIL |bb-plugin-provider-claude-code:isolated| src/bridge/provider-maintenance.config-dir.test.ts > reads the configured account identity when both profiles have current credentials
bb-plugin-provider-claude-code:test: AssertionError: expected { supported: true, usage: { …(4) } } to match object { usage: { status: 'ok', …(1) } }
bb-plugin-provider-claude-code:test: (3 matching properties omitted from actual)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: - Expected
bb-plugin-provider-claude-code:test: + Received
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: {
bb-plugin-provider-claude-code:test: "usage": {
bb-plugin-provider-claude-code:test: - "accountEmail": "configured@example.invalid",
bb-plugin-provider-claude-code:test: + "accountEmail": "default@example.invalid",
bb-plugin-provider-claude-code:test: "status": "ok",
bb-plugin-provider-claude-code:test: },
bb-plugin-provider-claude-code:test: }
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ❯ src/bridge/provider-maintenance.config-dir.test.ts:66:18
bb-plugin-provider-claude-code:test: 64| await fs.writeFile(path.join(state.home, ".claude", ".credentials.js…
bb-plugin-provider-claude-code:test: 65| const result = await getClaudeProviderUsage();
bb-plugin-provider-claude-code:test: 66| expect(result).toMatchObject({ usage: { status: "ok", accountEmail: …
bb-plugin-provider-claude-code:test: | ^
bb-plugin-provider-claude-code:test: 67| });
bb-plugin-provider-claude-code:test: 68|
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: Test Files 1 failed (1)
bb-plugin-provider-claude-code:test: Tests 3 failed | 1 passed (4)
bb-plugin-provider-claude-code:test: Start at 07:36:56
bb-plugin-provider-claude-code:test: Duration 448ms (transform 232ms, setup 0ms, import 348ms, tests 16ms, environment 0ms)
bb-plugin-provider-claude-code:test:
bb-plugin-provider-claude-code:test: ELIFECYCLE Test failed. See above for more details.
bb-plugin-provider-claude-code#test: ERROR command (TEMP_CHECKOUT/verify/plugins/provider-claude-code) TEMP_CHECKOUT/bin/pnpm run test provider-maintenance.config-dir.test.ts exited (1)
Tasks: 4 successful, 5 total
Cached: 0 cached, 5 total
Time: 2.353s
Failed: bb-plugin-provider-claude-code#test
ERROR run failed: command exited (1)