Skip to content

[Bug]: Account switching creates a new managed home each time, seeded with stale credentials #561

Description

@skyeyesec333

Existing issues

  • I searched existing issues and did not find a duplicate.

What happened?

materialize_as_managed creates a new UUID-named managed home on every call:

// rust/src/codex_accounts/account_manager.rs:283
let destination_home = managed_homes_directory().join(Uuid::new_v4().to_string());
fs::create_dir_all(&destination_home)?;
fs::copy(&source_auth_path, destination_home.join("auth.json"))?;

switch_account calls it whenever the outgoing ambient account differs from the target (account_manager.rs:228-233). Every switch away from the ambient identity therefore leaves another managed home behind. Nothing dedupes or prunes them.

Each new home is seeded by copying the current ambient auth.json. Once that file goes stale, every home created afterwards holds the same expired token. My install reached 24 managed homes for 2 accounts over about 10 days of normal switching.

Expected: one managed home per account, holding that account's current credentials.
Actual: one extra home per switch, each holding whatever the ambient auth.json contained at that moment.

A PR with a fix and tests follows.

Prior art

Searched open and closed issues for: managed home, duplicate account, Authentication required, auth.json, codex account, switch account, backoff.

#468 and #533 report the same warning from a different cause. Both concern credentials that are still valid being rejected by the 8-day last_refresh gate. This report is about credentials that genuinely expired, because the app kept cloning a frozen auth.json instead of refreshing one. Fixing #533 would not prevent this case: these tokens were past their JWT exp and would still be rejected, correctly.

I found nothing covering managed-home duplication, and nothing covering the backoff failing to re-arm after credentials change.

One observation I cannot confirm from outside: #468's reproduction mentions last_refresh about 215 hours old with the CLI still logged in. That is consistent with an install that had been cloning a stale credential for nine days, rather than one that sat idle.

Evidence

24 directories, 12 per account, created in pairs seconds apart, which is what switch materializing the outgoing account looks like:

2026-09-09 01:30:54    2026-09-10 02:14:03    2026-09-15 08:04:20
2026-09-09 01:31:09    2026-09-10 02:14:11    2026-09-15 12:09:24
2026-09-09 01:31:49    2026-09-10 03:56:56    2026-09-15 12:09:30
2026-09-09 01:31:55    2026-09-10 03:57:04    2026-09-17 12:06:07
2026-09-09 01:32:15    2026-09-10 04:42:07    2026-09-17 13:21:35
2026-09-10 01:52:41    2026-09-10 04:44:38    2026-09-17 13:21:39
2026-09-10 01:52:46    2026-09-12 08:05:46    2026-09-17 14:19:42
2026-09-10 01:56:53    2026-09-12 08:05:52    2026-09-12 08:15:18

Every auth.json across all 24 homes had one of two modification times, both from the first day:

2026-09-09 01:30:54   (account A)
2026-09-09 01:31:09   (account B)

Homes created on Sep 10, 12, 15 and 17 held credentials stamped Sep 9. The ambient file was stale as well (%USERPROFILE%\.codex\auth.json, JWT exp 2026-09-09 02:30), so repeated browser sign-ins never produced a fresh stored credential.

Once the credentials died, every poll failed for about a day, then polling stopped. A valid credential written by codex login did not revive it:

09:13:42  WARN codexbar::providers::codex: Codex API fetch failed: Authentication required
09:17:58  WARN codexbar::providers::codex: Codex API fetch failed: Authentication required
          codex login writes a valid token at 09:19:28 (JWT exp 10:19:26)
          no further providers::codex lines for 13+ minutes

Only restarting the app resumed polling.

accounts.json also kept pointing at a managed home that no longer existed, with no self-healing:

WARN codexbar::codex_accounts::fetch_coordination: Could not synchronize the active Codex
account's managed credentials: The system cannot find the path specified. (os error 3)

Recovery took quitting the app, clearing managed-homes\ and accounts.json by hand, running codex login, and relaunching. After that one home per account was created with current tokens, and usage fetched normally.

Affected area

  • Tray panel
  • Settings UI
  • Config file / settings persistence
  • CLI
  • Provider-specific behavior
  • Installer / release packaging
  • Startup / background behavior
  • Other

Steps to reproduce

  1. Sign in to Codex CLI so an ambient ~/.codex identity exists.
  2. Add a second account in CodexBar and use Switch.
  3. Switch back.
  4. Look at %APPDATA%\CodexBar\codex-accounts\managed-homes\.

One extra directory appears per switch. Left alone for days, the copied credentials expire and the provider enters the loop shown above.

Logs, screenshots, or recordings

2026-09-08T14:52:21 WARN codexbar::codex_accounts::fetch_coordination: Could not synchronize
  the active Codex account's managed credentials: The system cannot find the path specified.
  (os error 3)
2026-09-19T09:13:42 WARN codexbar::providers::codex: Codex API fetch failed: Authentication required
2026-09-19T09:17:58 WARN codexbar::providers::codex: Codex API fetch failed: Authentication required

From %APPDATA%\CodexBar\logs\codexbar-desktop.log. Credentials, emails and account identifiers withheld.

App version

0.60.3

Windows version

Windows 11

Additional context

The PR fixes only the duplicate-home creation. Two related behaviours remain, and I am happy to file them separately if you prefer:

  1. Backoff does not re-arm when credentials change. This is the more damaging half: it turns a recoverable auth failure into an app that needs restarting. A new or refreshed auth.json, or any add or switch, could reset the poller, and the backoff could use a ceiling.
  2. Authentication required is invisible in the UI. I only found it by reading the log file. A sign-in prompt on the affected account row would make this self-service.

Existing installs will still carry the homes they already accumulated. The PR stops new ones but does not prune. Removing homes not referenced by accounts.json at startup would clean those up.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions