JuliusBrussee/caveman · error · Error
CODEX_HOME points to
Error message
CODEX_HOME points to ${JSON.stringify(configured)}, but that path is not a directory What it means
Thrown when CODEX_HOME is set and stat succeeds, but the path is not a directory (e.g. it is a regular file, symlink to a file, or socket). The CLI requires CODEX_HOME to be a directory because it stores auth.json and other state under it.
Solutions
- Check the path: `file "$CODEX_HOME"` or `ls -ld` — replace it with a directory
- Point CODEX_HOME at a proper directory (create it with mkdir -p if needed) or unset CODEX_HOME to use the default (~/.codex)
- If a file occupies the intended path, move the file aside and create the directory
Example fix
// before export CODEX_HOME=/home/user/.codex/auth.json // after export CODEX_HOME=/home/user/.codex
Defensive patterns
Strategy: validation
Validate before calling
const configured = process.env.CODEX_HOME;
if (configured && fs.existsSync(configured) && !fs.statSync(configured).isDirectory()) {
throw new Error(`CODEX_HOME must be a directory, got: ${configured}`);
} Type guard
function isDirectoryPath(p: string): boolean {
try { return fs.statSync(p).isDirectory(); } catch { return false; }
} Try / catch
try {
runCodexCommand();
} catch (e) {
if (String(e.message).includes("is not a directory")) {
console.error(`CODEX_HOME must point to a directory; got ${process.env.CODEX_HOME}`);
}
} Prevention
- Set CODEX_HOME to a directory, never a file such as auth.json
- Use `ls -ld "$CODEX_HOME"` to confirm the path type in shell scripts
- Unset CODEX_HOME to fall back to the default ~/.codex directory
When it happens
Trigger: CODEX_HOME env var points to an existing non-directory path, so metadata.isDirectory() returns false during codexHomeDir().
Common situations: CODEX_HOME accidentally set to the auth.json file itself, to a downloaded archive, or to a path that was replaced by a file during a migration/restore.
Related errors
- CODEX_HOME points to
- failed to read CODEX_HOME
- CAVEMAN_AUTH_TOKEN must be at least
- CAVEMAN_CCR_MAX_BYTES must be a positive integer
- ccr sqlite path is required
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3846e385dbbd6be6.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:6203
}
export function codexHomeDir(env: NodeJS.ProcessEnv = process.env): string {
const configured = env.CODEX_HOME;
if (!configured) return join(homedir(), ".codex");
// Match Codex's own home resolver: a nonempty override may be relative, but
// must already be a directory and is canonicalized before use. Never fall
// back to another account's default home when the override is invalid.
let metadata: ReturnType<typeof statSync>;
try {
metadata = statSync(configured);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
throw new Error(`CODEX_HOME points to ${JSON.stringify(configured)}, but that path does not exist`);
}
throw new Error(`failed to read CODEX_HOME ${JSON.stringify(configured)}: ${(error as Error).message}`);
}
if (!metadata.isDirectory()) {
throw new Error(`CODEX_HOME points to ${JSON.stringify(configured)}, but that path is not a directory`);
}
try {
return realpathSync(configured);
} catch (error) {
throw new Error(`failed to canonicalize CODEX_HOME ${JSON.stringify(configured)}: ${(error as Error).message}`);
}
}
function codexAuthPath(): string {
return join(codexHomeDir(), "auth.json");
}
function nonEmptyString(v: unknown): v is string {
return typeof v === "string" && v.trim().length > 0;
}
function readCodexAuthJson(): JsonObject | undefined {
const path = codexAuthPath();View on GitHub (pinned to 3ee70a1026)