#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

ClaimFindingEvidence
Configured credentials are ignoredVerifiedUsage and health return expired with a current custom profile.
Account email is read from the wrong profileVerifiedBoth-current fixture returns default email.
Live account and shipped release exhibit the bugUnverifiedNo real account or historical bundle was inspected.
An SDK resolver existsVerified with qualificationThe helper is private, not a directly reusable exported function.
Custom files should override macOS KeychainNot establishedCredential 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

  1. Run the checkout/install/build commands below.
  2. Save the inline test below into plugins/provider-claude-code/src/bridge/.
  3. 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)