Yeachan-Heo/oh-my-codex · critical · Error

[api] failed to launch native binary: executable not found (

Error message

[api] failed to launch native binary: executable not found (${binaryPath})

What it means

`omx api` resolved a binary path but spawning it failed with an error classified as 'missing' (typically ENOENT), meaning the file at binaryPath does not exist or is not executable at spawn time. The path existed during resolution but vanished or is inaccessible when passed to spawnSync/execFile.

Source

Thrown at src/cli/api.ts:221

function isHelpRequest(args: readonly string[]): boolean {
  if (args.length === 0) return true;
  return args.includes('--help') || args.includes('-h');
}

export async function apiCommand(args: string[]): Promise<void> {
  if (isHelpRequest(args)) {
    console.log(API_USAGE);
    return;
  }

  const binaryPath = await resolveApiBinaryPathWithHydration();

  const result = runApiBinary(binaryPath, args);
  if (result.error) {
    const errno = result.error as NodeJS.ErrnoException;
    const kind = classifySpawnError(errno);
    if (kind === 'missing') throw new Error(`[api] failed to launch native binary: executable not found (${binaryPath})`);
    if (kind === 'blocked') throw new Error(`[api] failed to launch native binary: executable is blocked (${errno.code || 'blocked'})`);
    throw new Error(`[api] failed to launch native binary: ${errno.message}`);
  }

  writeApiResultOutput(result);
  if (result.status !== 0) {
    process.exitCode = typeof result.status === 'number'
      ? result.status
      : resolveSignalExitCode(result.signal);
  }
}

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Re-run the command (transient deletion races usually clear) and reinstall/re-hydrate the binary if it persists
  2. Verify the file actually exists and is not a broken symlink: `ls -l <binaryPath>`
  3. Set OMX_API_BIN_ENV to a known-good binary location
  4. Check that the target filesystem is mounted and accessible inside containers

Example fix

# before
omx api status   # ENOENT at spawn
# after
ls -l /path/to/omx-api   # confirm it exists
omx api status
Defensive patterns

Strategy: retry

Validate before calling

import { existsSync, statSync } from 'node:fs';
const ok = existsSync(binPath) && statSync(binPath).isFile();
if (!ok) throw new Error(`binary missing before launch: ${binPath}`);

Try / catch

catch (e) { if (/executable not found \(\S+omx-api/.test(String(e))) { await rehydrateBinary(); retry(); } else throw e; }

Prevention

When it happens

Trigger: Calling `omx api ...` where the resolved path was deleted between resolution and spawn, is a dangling symlink, sits on an unmounted filesystem, or where the interpreter/loader referenced by the binary is absent.

Common situations: Race conditions where another process cleans node_modules or the cache mid-run; dangling symlinks in the managed cache; container filesystems mounted lazily; the binary present but its dynamic loader missing on minimal images.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/4a8a59dd07329d2b. Report an issue: GitHub.