{"record":{"id":"1443b7567b72dc81","repo":"thedotmack/claude-mem","slug":"codex-args-join-failed-with-exit-code-ex","errorCode":null,"errorMessage":"codex ${args.join(' ')} failed with exit code ${exitCode}${stderr ? `: ${stderr}` : ''}","messagePattern":"codex (.+?) failed with exit code (.+?)(.+?)` : ''\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/integrations/CodexCliInstaller.ts","lineNumber":160,"sourceCode":"  const invocation = resolveCodexSpawnInvocation(args);\n  return spawnSync(invocation.command, invocation.args, invocation.options);\n}\n\nfunction runCodex(args: string[]): void {\n  const result = codexSpawn(args);\n  const output = console;\n  const stdout = result.stdout?.trimEnd();\n  const stderr = result.stderr?.trimEnd();\n\n  if (stdout) output.log(stdout);\n  if (stderr) output.error(stderr);\n\n  if (result.error) {\n    throw result.error;\n  }\n  if (result.status !== 0) {\n    const exitCode = result.status ?? 'unknown';\n    throw new Error(`codex ${args.join(' ')} failed with exit code ${exitCode}${stderr ? `: ${stderr}` : ''}`);\n  }\n}\n\nfunction isMarketplaceDifferentSourceError(error: unknown): boolean {\n  const message = error instanceof Error ? error.message : String(error);\n  return message.includes(`marketplace '${MARKETPLACE_NAME}' is already added from a different source`)\n    || message.includes(`marketplace \\`${MARKETPLACE_NAME}\\` is already added from a different source`);\n}\n\nfunction registerCodexMarketplace(marketplaceRoot: string): void {\n  try {\n    runCodex(['plugin', 'marketplace', 'add', marketplaceRoot]);\n    return;\n  } catch (error) {\n    if (!isMarketplaceDifferentSourceError(error)) {\n      throw error instanceof Error ? error : new Error(String(error));\n    }\n  }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/integrations/CodexCliInstaller.ts#L142-L178","documentation":"runCodex() is the wrapper that spawns the `codex` CLI (resolved to codex.cmd on Windows). If the child process exits with a non-zero status (and did not fail to spawn), it throws an Error echoing the exact args, the exit code, and (when present) the trimmed stderr. This surfaces real codex failures such as marketplace add/remove conflicts that are not the recoverable 'already added from a different source' case.","triggerScenarios":"Any codex subcommand run by the installer exits non-zero: `codex plugin marketplace add`/`remove` fails for a reason other than the recognized different-source conflict; a codex config write command errors; codex itself crashes or hits a permission error. The recognized different-source conflict is filtered out earlier in registerCodexMarketplace and does NOT reach this throw.","commonSituations":"Codex config dir ~/.codex is read-only or owned by another user; codex version behaves differently than expected for a subcommand; the marketplace path passed to `add` is unreachable; a stale lock in ~/.codex; codex hit an internal panic and wrote it to stderr.","solutions":["Read the exit code and stderr in the message — they are the literal codex output, so fix the underlying codex error.","If it is a permissions issue, check ownership/permissions of ~/.codex and its config files.","Re-run the exact codex command shown in the args manually to reproduce and debug interactively.","Update or reinstall the Codex CLI if the failure is a known bug in the installed version.","Clear any stale codex locks/state and retry the install."],"exampleFix":"# before — codex marketplace add fails\ncodex plugin marketplace add /path/to/root\n# nonzero exit -> runCodex throws\n\n# after — run manually to see full stderr, fix root cause, retry\ncodex plugin marketplace add /path/to/root\nchmod -R u+w ~/.codex   # if permissions\nnpx claude-mem@latest install --codex","handlingStrategy":"try-catch","validationCode":"import { commandExists } from './codex-utils.js';\n// Pre-flight: confirm codex is on PATH before invoking runCodex.\nfunction ensureCodexAvailable(): void {\n  if (!commandExists('codex') && process.platform !== 'win32') {\n    throw new Error('codex CLI not found on PATH');\n  }\n}","typeGuard":"function isCodexRunFailure(e: unknown): boolean {\n  return e instanceof Error && /codex .* failed with exit code/i.test(e.message);\n}","tryCatchPattern":"try {\n  runCodex(['plugin', 'marketplace', 'add', marketplaceRoot]);\n} catch (e) {\n  if (isMarketplaceDifferentSourceError(e)) {\n    runCodex(['plugin', 'marketplace', 'remove', MARKETPLACE_NAME]);\n    runCodex(['plugin', 'marketplace', 'add', marketplaceRoot]);\n    return;\n  }\n  // Real failure — echo args + stderr for the operator.\n  throw e;\n}","preventionTips":["Run the exact codex subcommand manually first to surface real errors before automating.","Check ~/.codex ownership/permissions so codex can write config.","Keep codex CLI current to avoid subcommand regressions."],"tags":["codex","cli","installer","process","subprocess"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}