JuliusBrussee/caveman · error · Error
CODEX_HOME points to
Error message
CODEX_HOME points to ${JSON.stringify(configured)}, but that path does not exist What it means
The CLI honors a CODEX_HOME environment variable override for the Codex home directory, but deliberately does not fall back to a default when the override is set and invalid — falling back silently could route to another account's home. If statSync on the configured path fails with ENOENT, it throws naming the exact configured value.
Solutions
- Create the directory: mkdir -p "$CODEX_HOME"
- Unset CODEX_HOME (or fix the typo) so the CLI uses the default Codex home
- Point CODEX_HOME at an existing directory, e.g. export CODEX_HOME=$HOME/.codex
- Check for typos and variable expansion failures in the shell profile that sets CODEX_HOME
- In containers/CI, ensure the CODEX_HOME volume is mounted/created before the CLI runs
Example fix
// before export CODEX_HOME=$HOME/.codexx # does not exist // after export CODEX_HOME=$HOME/.codex # or: mkdir -p "$CODEX_HOME"
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync, statSync } from 'fs';
const home = process.env.CODEX_HOME;
if (home && (!existsSync(home) || !statSync(home).isDirectory())) {
throw new Error(`CODEX_HOME=${home} is missing or not a directory`);
} Try / catch
try {
cli.codexCommand(args);
} catch (err) {
if ((err as Error).message.includes('but that path does not exist')) {
const p = JSON.parse((err as Error).message.match(/CODEX_HOME points to (\".*?\")/)?.[1] ?? '"?"');
console.error(`Create ${p} (mkdir -p) or unset/fix CODEX_HOME.`);
} else throw err;
} Prevention
- Never silently fall back from an invalid CODEX_HOME — fix or unset it
- Run mkdir -p on CODEX_HOME paths in container/CI entrypoints
- Check for typos and shell-expansion failures wherever CODEX_HOME is set
- Verify the path exists and is a directory after machine or container migrations
When it happens
Trigger: CODEX_HOME is set to a path that does not exist when the CLI resolves the Codex home: statSync(configured) throws with code ENOENT — a typo'd path, a deleted/moved directory, or a path that was never created (e.g. ~/codex-home vs ~/.codex).
Common situations: CODEX_HOME pointing at a removed dotfile directory after cleaning ~/.codex; a docker/CI container where the volume mount for CODEX_HOME was never created; switching machines where the old home path doesn't exist; typos like CODEX_HOME=$HOME/.codexx.
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_HOME points to
- failed to canonicalize CODEX_HOME
- failed to read CODEX_HOME
- contains an invalid path character
- azure legacy inference path
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3f1ffac3e68e9161.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/index.ts:6198
function agentUserPath(agent: string, path: string): string {
const prefix = agent === "claude" ? "~/.claude/" : agent === "codex" ? "~/.codex/" : undefined;
if (!prefix || !path.startsWith(prefix)) return path;
const root = agent === "claude" ? claudeConfigDir() : codexHomeDir();
return join(root, path.slice(prefix.length));
}
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 {View on GitHub (pinned to 3ee70a1026)