affaan-m/ECC · error · Error

ECC_ITO_CLI_EXECUTABLE must point to the canonical…

Error message

ECC_ITO_CLI_EXECUTABLE must point to the canonical dist/bin/ito.js entry.

What it means

scripts/ito.js is a thin bridge that invokes the separately installed canonical Itô CLI and refuses to discover it via PATH. When ECC_ITO_CLI_EXECUTABLE is set, assertUsableExecutable resolves the path and checks it matches the canonical entry ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito.js. This error means the override points at a readable file but one that is NOT that canonical built entry (a shim, source file, or wrong binary), so the bridge refuses to run it.

Solutions

  1. Build the canonical package (git clone https://github.com/Ito-Markets/ito-cloud-runtime.git, cd ito-cloud-runtime/cli/ito-compute-cli, npm ci, npm run check) so dist/bin/ito.js exists.
  2. Set ECC_ITO_CLI_EXECUTABLE to the absolute path ending in cli/ito-compute-cli/dist/bin/ito.js, e.g. /absolute/path/to/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito.js.
  3. Verify the resolved path contains the expected segments (cli/ito-compute-cli/dist/bin/ito.js) rather than a symlink target elsewhere; use the real absolute path, not a symlink.
  4. If a wrapper is unavoidable, make the wrapper exec the canonical dist/bin/ito.js and point the override at that canonical file instead.

Example fix

// before
export ECC_ITO_CLI_EXECUTABLE=$(which ito)              # npm shim -> rejected
// after
export ECC_ITO_CLI_EXECUTABLE="$HOME/src/ito-cloud-runtime/cli/ito-compute-cli/dist/bin/ito.js"
Defensive patterns

Strategy: validation

Validate before calling

const p = process.env.ECC_ITO_CLI_EXECUTABLE;
const canonical = p && p.endsWith('/cli/ito-compute-cli/dist/bin/ito.js') && require('path').isAbsolute(p);
if (!canonical) throw new Error('Set ECC_ITO_CLI_EXECUTABLE to the absolute .../cli/ito-compute-cli/dist/bin/ito.js path');

Type guard

function isCanonicalItoEntry(p) { return typeof p === 'string' && require('path').isAbsolute(p) && p.split(require('path').sep).join('/').endsWith('/cli/ito-compute-cli/dist/bin/ito.js'); }

Prevention

When it happens

Trigger: Setting ECC_ITO_CLI_EXECUTABLE to a wrapper/shell shim, to the TypeScript source cli/ito-compute-cli/src/ito.ts, to dist/bin/ito-mcp.js, to a globally installed package entry, or to a repo checkout where the dist output was moved/renamed; the path passes the readability check but fails isCanonicalItoEntry (segments .../cli/ito-compute-cli/dist/bin/ito.js).

Common situations: Developers point the override at an npx/npm-shim in node_modules/.bin, at a copied binary elsewhere, or at an older layout of the ito-cloud-runtime checkout (pre-dist build or renamed package path). Also common after building to a custom outDir.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/349a132f10d501e6. Report an issue: GitHub.

Appendix: source

Thrown at scripts/ito.js:217

  if (!path.isAbsolute(configured)) {
    throw new Error(
      `${EXECUTABLE_OVERRIDE} must be an absolute path explicitly configured by the operator.`
    );
  }
  return assertUsableExecutable(configured);
}

function assertUsableExecutable(candidate) {
  let canonicalCandidate;
  try {
    canonicalCandidate = fs.realpathSync.native(candidate);
  } catch {
    throw new Error(
      `${EXECUTABLE_OVERRIDE} does not point to a readable local Itô CLI file.`
    );
  }
  if (!isCanonicalItoEntry(canonicalCandidate)) {
    throw new Error(
      `${EXECUTABLE_OVERRIDE} must point to the canonical dist/bin/ito.js entry.`
    );
  }
  if (!isUsableExecutable(canonicalCandidate)) {
    throw new Error(
      `${EXECUTABLE_OVERRIDE} does not point to a readable local Itô CLI file.`
    );
  }
  return canonicalCandidate;
}

function isCanonicalItoEntry(candidate) {
  const pathSegments = path
    .normalize(candidate)
    .split(path.sep)
    .filter(Boolean);
  if (pathSegments.length < CANONICAL_ENTRY_SEGMENTS.length) return false;
  const candidateTail = pathSegments.slice(-CANONICAL_ENTRY_SEGMENTS.length);

View on GitHub (pinned to 8321021c54)