Yeachan-Heo/oh-my-codex · error · Error
auth directory must not be a symlink: ${dir}
Error message
auth directory must not be a symlink: ${dir} What it means
The second-pass batch proof in requireFrozenWindowTopologySync found a pane that is definitively gone ('gone') while the frozen topology still expects it live. This catches panes that died during the tiny window between the first and second validation passes (or after passing pass one).
Source
Thrown at src/auth/paths.ts:57
}
export function resolveDefaultCodexHome(home = homedir()): string {
return join(home, ".codex");
}
export function resolveLiveAuthPath(
cwd = process.cwd(),
env: NodeJS.ProcessEnv = process.env,
home = homedir(),
): string {
const codexHome = resolveCodexHomeForLaunch(cwd, env) || resolveDefaultCodexHome(home);
return join(codexHome, "auth.json");
}
export async function ensurePrivateDir(dir: string): Promise<void> {
await mkdir(dir, { recursive: true, mode: AUTH_DIR_MODE });
const info = await lstat(dir);
if (info.isSymbolicLink()) throw new Error(`auth directory must not be a symlink: ${dir}`);
if (!info.isDirectory()) throw new Error(`auth path is not a directory: ${dir}`);
if (process.platform !== "win32") {
const { chmod } = await import("fs/promises");
await chmod(dir, AUTH_DIR_MODE).catch(() => undefined);
}
}
export async function assertReadableFile(path: string, label: string): Promise<void> {
try {
const info = await stat(path);
if (!info.isFile()) throw new Error(`${label} is not a file: ${path}`);
} catch (err) {
if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
throw new Error(`${label} not found: ${path}`);
}
throw err;
}
}View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Enable remain-on-exit on team panes so exited panes stay until deliberately killed
- Fix worker processes that exit prematurely
- Retry/rebuild: a lost pane invalidates the frozen topology — recreate the session
- Coordinate all pane-killing through the library's own teardown APIs
Example fix
# keep dead panes around so topology checks stay consistent tmux set-option -t myteam remain-on-exit on
Defensive patterns
Strategy: validation
Validate before calling
runTmuxOk(['set-option', '-t', sessionName, 'remain-on-exit', 'on']);
Try / catch
catch (err) { if (/not proven live/.test(err.message)) { rebuildTeamSession(); } } Prevention
- remain-on-exit on for team panes
- Fix prematurely exiting workers
- Route all kills through library teardown
When it happens
Trigger: A pane exiting or being killed between the first per-pane proof and the final batched proof within a single topology validation call.
Common situations: Worker processes exiting under load, scripted pane kills racing the operation, or remain-on-exit off combined with flaky worker processes.
Related errors
- invalid auth slot path
- auth path is not a directory: ${dir}
- ${label} is not a file: ${path}
- tmux window topology changed before layout mutation: target=
- ${label} not found: ${path}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/2fab566d6aaa0ef9.
Report an issue: GitHub.