openai/codex · error · Error

Missing optional dependency ${platformPackage}. Reinstall Co

Error message

Missing optional dependency ${platformPackage}. Reinstall Codex: ${updateCommand}

What it means

normalize_query_name rejects an empty query-parameter name. It is called from validate_query_constraints at config-load time and again when a QueryConstraint is compiled for live request matching, so an empty key fails twice on the same config. The message matches the defensive check in validate_query_constraints, but this is the site that actually fires first for an empty key. The proxy needs the name to select which query parameter to match, so an empty name is always a config bug.

Source

Thrown at codex-cli/bin/codex.js:105

  const codexExecutable = path.join(
    vendorRoot,
    targetTriple,
    "bin",
    process.platform === "win32" ? "codex.exe" : "codex",
  );
  if (existsSync(codexExecutable)) {
    return codexExecutable;
  }

  const packageManager = detectPackageManager();
  const updateCommand =
    packageManager === "bun"
      ? "bun install -g @openai/codex@latest"
      : packageManager === "pnpm"
        ? "pnpm add -g @openai/codex@latest"
        : "npm install -g @openai/codex@latest";
  throw new Error(
    `Missing optional dependency ${platformPackage}. Reinstall Codex: ${updateCommand}`,
  );
}

const binaryPath = findCodexExecutable();

// Use an asynchronous spawn instead of spawnSync so that Node is able to
// respond to signals (e.g. Ctrl-C / SIGINT) while the native binary is
// executing. This allows us to forward those signals to the child process
// and guarantees that when either the child terminates or the parent
// receives a fatal signal, both processes exit in a predictable manner.

function isPnpmOwnedCodexInstall(nodeModulesDir) {
  if (!existsSync(path.join(nodeModulesDir, ".modules.yaml"))) {
    return false;
  }

  try {

View on GitHub (pinned to 339751715c)

Solutions

  1. Delete the empty-string key from match.query
  2. Restore the intended parameter name, e.g. query = { ref = ["heads/main"] }
  3. Sanitize generated configs before load: reject or drop empty map keys in the generator

Example fix

// config.toml — before
[network.mitm_hooks.match.query]
"" = ["heads/main"]

// after
[network.mitm_hooks.match.query]
ref = ["heads/main"]
Defensive patterns

Strategy: validation

Validate before calling

// Runs before both validation and hook compilation
if hook.matcher.query.keys().any(|k| k.is_empty()) {
    return Err(anyhow!("mitm hook for {} has an empty query key", hook.host));
}

Type guard

fn query_keys_valid(hook: &MitmHookConfig) -> bool {
    hook.matcher.query.keys().all(|k| !k.is_empty())
}

Prevention

When it happens

Trigger: An empty-string key in a hook's match.query map — TOML query = { "" = [...] } or a Rust-built map with an empty String key. Hit once via validate_mitm_hook_config at startup and again via QueryConstraint construction during hook compilation.

Common situations: Same shapes as the duplicate check at mitm_hook.rs:566: template-generated TOML with unfilled placeholders, programmatic map construction with computed (possibly empty) keys, and copy-pasted hook examples with the key name stripped.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/b3c11711596ecaf5. Report an issue: GitHub.