paperclipai/paperclip · error
codex auth cache: account-home directory no longer exists; r
Error message
codex auth cache: account-home directory no longer exists; refusing to write a secret that names it
What it means
assertAccountHomeCacheDirStillValid() checks that the account-home directory still exists on disk before createManagedLocalSecret() writes a secret whose name references that directory. If stat fails with ENOENT the directory is gone, and writing a secret pointing at a nonexistent home would leave dangling, unusable credentials — so the write is refused.
Source
Thrown at packages/adapters/codex-local/src/server/codex-auth-cache.ts:355
* under the cache root can ever be an account-home directory, so this never
* rejects an unrelated `local_encrypted` secret write, such as an API key or
* a hand-typed token.
*/
export async function assertAccountHomeCacheDirStillValid(
env: NodeJS.ProcessEnv = process.env,
companyId: string,
value: string,
): Promise<void> {
const cacheRoot = resolveCodexAuthCacheDir(env, companyId);
if (!value.startsWith(cacheRoot + path.sep)) return;
const exists = await lstat(value)
.then(() => true)
.catch((error: NodeJS.ErrnoException) => {
if (error.code === "ENOENT") return false;
throw error;
});
if (!exists) {
throw new Error(
"codex auth cache: account-home directory no longer exists; refusing to write a secret that names it",
);
}
}
/**
* Reads the usable subscription `account_id` from an `auth.json` payload. Returns
* `null` for an absent, unusable, or api-key credential (no subscription
* identity). This mirrors `parseAuth` in `codex-auth-merge-decision.cjs`; keep
* the two in step when the auth format changes.
*
* The returned value is the exact, untrimmed `account_id` string. A caller
* passes it on to {@link toAccountHandle} unchanged: that function is the
* one place that decides whether surrounding whitespace is acceptable, and it
* must see the raw value to reject an identifier that differs from another
* one only by whitespace. Trimming here, before that check runs, would let
* two distinct identifiers collapse onto the same account handle.
*/View on GitHub (pinned to 01ad858492)
Solutions
- Recreate the account home by re-running the Codex device login / promotion so the directory is re-established, then retry the secret write.
- Verify the account-home directory path exists (fs.stat) and that the expected handle-derived directory is present before writing.
- If the account is genuinely gone, remove the stale secret/cache entry so it no longer references a missing home.
- Check nothing in your cleanup scripts or tmp cleaners deletes the Codex account-home directory while the adapter is using it.
Example fix
// before
await createManagedLocalSecret(secretService, { accountHandle, ... });
// after
const homeDir = resolveAccountHomeDir(accountHandle);
if (!existsSync(homeDir)) {
throw new Error(`account home missing: ${homeDir}; re-run codex login before writing secrets`);
}
await createManagedLocalSecret(secretService, { accountHandle, ... }); Defensive patterns
Strategy: try-catch
Validate before calling
import { stat } from "node:fs/promises";
async function accountHomeExists(dir: string): Promise<boolean> {
try { await stat(dir); return true; } catch (e: any) { if (e.code === "ENOENT") return false; throw e; }
}
if (!(await accountHomeExists(homeDir))) {
await reRunCodexLogin(); // recreate home before any secret write
} Try / catch
try {
await createManagedLocalSecret(secretService, params);
} catch (err) {
if (err instanceof Error && err.message.includes("account-home directory no longer exists")) {
await reRunCodexLoginAndPromotion(); // rebuild home, then retry once
await createManagedLocalSecret(secretService, params);
return;
}
throw err;
} Prevention
- Exclude the Codex account-home and auth-cache directories from tmp cleaners and cleanup cron jobs.
- After any container/workspace rebuild, re-run device login before writing secrets.
- Periodically reconcile stored secrets against existing account homes and prune stale entries.
- Check home directory existence during startup health checks so the gap is caught before writes.
When it happens
Trigger: Calling createManagedLocalSecret() (directly or via secretService) after the account-home directory was deleted or moved — e.g. manual cleanup of ~/.codex or the cache root, an OS temp cleaner removing it, or a home migration that did not recreate the directory.
Common situations: User manually deleted the Codex home/account directory; disk cleanup tools purged cache dirs; the account was logged out elsewhere while the local secret store still references its home; workspace/container rebuilds wiping home directories but not secrets.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- codex auth cache: account_id is not a valid account handle
- Codex working directory must exist before provider admission
- Codex working directory cannot overlap sensitive host HOME s
- codex_startup_trust_cannot_preserve_configuration
- native_runner_control_plane_state_unsafe
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/1d150e97f702055a.
Report an issue: GitHub.