{"record":{"id":"769f5a42ecc26024","repo":"Yeachan-Heo/oh-my-codex","slug":"failed-to-launch-codex-login-executable-not-found","errorCode":null,"errorMessage":"failed to launch codex login: executable not found in PATH","messagePattern":"failed to launch codex login: executable not found in PATH","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/cli/auth.ts","lineNumber":50,"sourceCode":"  for (const arg of args) {\n    if (!allowed.has(arg)) {\n      throw new Error(`unsupported codex login flag for omx auth add: ${arg}`);\n    }\n  }\n}\n\nfunction runCodexLogin(cwd: string, env: NodeJS.ProcessEnv, loginArgs: string[] = []): void {\n  validateCodexLoginArgs(loginArgs);\n  const { result } = spawnPlatformCommandSync(\"codex\", [\"login\", ...loginArgs], {\n    cwd,\n    env,\n    stdio: \"inherit\",\n    encoding: \"utf-8\",\n  });\n  if (result.error) {\n    const error = result.error as NodeJS.ErrnoException;\n    const kind = classifySpawnError(error);\n    if (kind === \"missing\") throw new Error(\"failed to launch codex login: executable not found in PATH\");\n    if (kind === \"blocked\") throw new Error(`failed to launch codex login: executable is blocked (${error.code || \"blocked\"})`);\n    throw error;\n  }\n  if (result.status !== 0) {\n    throw new Error(`codex login exited with code ${result.status ?? 1}`);\n  }\n}\nasync function fileExists(path: string): Promise<boolean> {\n  try {\n    await readFile(path);\n    return true;\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return false;\n    throw error;\n  }\n}\n\nasync function createIsolatedLoginCodexHome(home: string | undefined): Promise<string> {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/auth.ts#L32-L68","documentation":"`omx auth add` spawns the `codex` CLI to perform login. When the spawn error classifies as 'missing' (ENOENT), it means no `codex` executable was found on PATH. The wrapper cannot authenticate without the underlying codex binary installed.","triggerScenarios":"Running `omx auth add <slot> ...` on a machine where the codex CLI is not installed, not on PATH in the current shell/CI, or where PATH is broken inside containers or GUI-launched terminals.","commonSituations":"Fresh machines without codex; nvm/asdf shims not initialized in CI; Docker images omitting codex; VS Code integrated terminal with different PATH than login shell.","solutions":["Install the codex CLI (e.g. `npm i -g @openai/codex` or the official installer)","Verify with `which codex` / `codex --version` in the same shell you run omx from","Fix PATH in CI/container so the codex install location is included","If codex is installed at a non-standard location, symlink it into a PATH dir or export PATH before running omx"],"exampleFix":"# before\nomx auth add work --device-auth   # codex: not found\n# after\nnpm i -g @openai/codex\nomx auth add work --device-auth","handlingStrategy":"validation","validationCode":"import { execFileSync } from 'node:child_process';\nlet hasCodex = false;\ntry { execFileSync('codex', ['--version'], { stdio: 'ignore' }); hasCodex = true; } catch {}\nif (!hasCodex) throw new Error('codex CLI not installed/on PATH');","typeGuard":null,"tryCatchPattern":"catch (e) { if (/executable not found in PATH/.test(String(e))) { await installCodex(); retry(); } else throw e; }","preventionTips":["Install codex before running omx auth add in setup scripts","Assert `command -v codex` in CI preflight","Initialize nvm/asdf shims in CI shells"],"tags":["auth","spawn","enoent","path","codex","dependency-missing"],"backgroundTag":"command-not-found-on-path","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}