{"record":{"id":"3846e385dbbd6be6","repo":"JuliusBrussee/caveman","slug":"codex-home-points-to-json-stringify-configured-but-that-path-3846e3","errorCode":null,"errorMessage":"CODEX_HOME points to ${JSON.stringify(configured)}, but that path is not a directory","messagePattern":"CODEX_HOME points to (.+?), but that path is not a directory","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":6203,"sourceCode":"}\n\nexport function codexHomeDir(env: NodeJS.ProcessEnv = process.env): string {\n  const configured = env.CODEX_HOME;\n  if (!configured) return join(homedir(), \".codex\");\n  // Match Codex's own home resolver: a nonempty override may be relative, but\n  // must already be a directory and is canonicalized before use. Never fall\n  // back to another account's default home when the override is invalid.\n  let metadata: ReturnType<typeof statSync>;\n  try {\n    metadata = statSync(configured);\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n      throw new Error(`CODEX_HOME points to ${JSON.stringify(configured)}, but that path does not exist`);\n    }\n    throw new Error(`failed to read CODEX_HOME ${JSON.stringify(configured)}: ${(error as Error).message}`);\n  }\n  if (!metadata.isDirectory()) {\n    throw new Error(`CODEX_HOME points to ${JSON.stringify(configured)}, but that path is not a directory`);\n  }\n  try {\n    return realpathSync(configured);\n  } catch (error) {\n    throw new Error(`failed to canonicalize CODEX_HOME ${JSON.stringify(configured)}: ${(error as Error).message}`);\n  }\n}\n\nfunction codexAuthPath(): string {\n  return join(codexHomeDir(), \"auth.json\");\n}\n\nfunction nonEmptyString(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim().length > 0;\n}\n\nfunction readCodexAuthJson(): JsonObject | undefined {\n  const path = codexAuthPath();","sourceCodeStart":6185,"sourceCodeEnd":6221,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L6185-L6221","documentation":"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.","triggerScenarios":"CODEX_HOME env var points to an existing non-directory path, so metadata.isDirectory() returns false during codexHomeDir().","commonSituations":"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.","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"],"exampleFix":"// before\nexport CODEX_HOME=/home/user/.codex/auth.json\n// after\nexport CODEX_HOME=/home/user/.codex","handlingStrategy":"validation","validationCode":"const configured = process.env.CODEX_HOME;\nif (configured && fs.existsSync(configured) && !fs.statSync(configured).isDirectory()) {\n  throw new Error(`CODEX_HOME must be a directory, got: ${configured}`);\n}","typeGuard":"function isDirectoryPath(p: string): boolean {\n  try { return fs.statSync(p).isDirectory(); } catch { return false; }\n}","tryCatchPattern":"try {\n  runCodexCommand();\n} catch (e) {\n  if (String(e.message).includes(\"is not a directory\")) {\n    console.error(`CODEX_HOME must point to a directory; got ${process.env.CODEX_HOME}`);\n  }\n}","preventionTips":["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"],"tags":["env-var","codex","config","path"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}