Yeachan-Heo/oh-my-codex · error

[sparkshell] failed to launch native binary: executable not…

Error message

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

What it means

sparkshell tried to launch its native sidecar binary and spawnSync classified the failure as 'missing' (ENOENT) — and an explicit binary override (OMX sparkshell bin env var) was set, so the tmux fallback path is skipped and the error is raised directly.

Solutions

  1. Fix the override path or unset it to allow fallback: verify with `ls -l "$OMX_SPARKSHELL_BIN"`
  2. Rebuild/reinstall the package so the bundled binary exists at the expected path
  3. With an override, no tmux fallback occurs — ensure the path is correct or intentionally omit the override

Example fix

# before
OMX_SPARKSHELL_BIN=/opt/sparkshell/sparkshell sparkshell bash  # missing file
# after
unset OMX_SPARKSHELL_BIN
sparkshell bash
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
const bin = process.env.OMX_SPARKSHELL_BIN;
if (bin && !existsSync(bin)) throw new Error(`override binary missing: ${bin}`);

Prevention

When it happens

Trigger: Setting the sparkshell bin env var to a path that does not exist, then running sparkshell.

Common situations: Pointing the override at a not-yet-built binary, a stale install path after an upgrade moved the sidecar, or typos in the env var value.

Related errors


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

Appendix: source

Thrown at src/cli/sparkshell.ts:438

    binaryPath = await resolveSparkShellBinaryPathWithHydration();
  } catch (error) {
    if (!hasExplicitOverride) {
      runSparkShellFallback(args, { cause: error, state: 'resolution-failed' });
      return;
    }
    throw error;
  }
  const result = runSparkShellBinary(binaryPath, args);

  if (result.error) {
    const errno = result.error as NodeJS.ErrnoException;
    const kind = classifySpawnError(errno);
    if (!hasExplicitOverride && (kind === 'missing' || kind === 'blocked')) {
      runSparkShellFallback(args, { cause: errno, nativePath: binaryPath, state: kind });
      return;
    }
    if (kind === 'missing') {
      throw new Error(`[sparkshell] failed to launch native binary: executable not found (${binaryPath})`);
    }
    if (kind === 'blocked') {
      throw new Error(`[sparkshell] failed to launch native binary: executable is blocked (${errno.code || 'blocked'})`);
    }
    throw new Error(`[sparkshell] failed to launch native binary: ${errno.message}`);
  }

  if (!hasExplicitOverride && isSparkShellNativeCompatibilityFailure(result)) {
    runSparkShellFallback(args, {
      cause: result.stderr || 'GLIBC-incompatible native sidecar',
      nativePath: binaryPath,
      state: 'glibc-incompatible',
    });
    return;
  }

  writeSparkShellResultOutput(result);

View on GitHub (pinned to 3ad79a8a6f)