affaan-m/ECC · error · Error

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

Error message

${EXECUTABLE_OVERRIDE} must point to the canonical dist/bin/ito.js entry.

What it means

After realpath succeeds, isCanonicalItoEntry verifies that the normalized absolute path ends with the exact canonical segment sequence CANONICAL_ENTRY_SEGMENTS (dist/bin/ito.js beneath cli/ito-compute-cli — see scripts/ito.js:16). This rejects wrappers, renamed entries, and alternative launchers so ECC only ever execs the audited entry file. Any path whose trailing segments do not match exactly fails here.

Solutions

  1. Point the variable at the exact built entry: <repo>/cli/ito-compute-cli/dist/bin/ito.js.
  2. If your build writes elsewhere, symlink or copy the artifact so the real path ends in cli/ito-compute-cli/dist/bin/ito.js, then point there.
  3. Run `node -e "console.log(require('fs').realpathSync.native(process.env.ECC_ITO_CLI_EXECUTABLE))"` to see what path ECC actually checks.

Example fix

# before
export ECC_ITO_CLI_EXECUTABLE="$HOME/src/ito-cloud-runtime/cli/ito-compute-cli/bin/ito.js"

# 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

import path from 'node:path';
const CANONICAL_SUFFIX = path.join('cli', 'ito-compute-cli', 'dist', 'bin', 'ito.js');
function isCanonicalEntry(p) {
  return path.normalize(p).endsWith(CANONICAL_SUFFIX);
}
function assertCanonicalItoEntry(p) {
  if (!isCanonicalEntry(p)) throw new Error(`Expected path ending in ${CANONICAL_SUFFIX}, got ${p}`);
  return p;
}

Type guard

function isCanonicalItoEntryPath(p) {
  return typeof p === 'string' && path.normalize(p).endsWith(path.join('cli', 'ito-compute-cli', 'dist', 'bin', 'ito.js'));
}

Prevention

When it happens

Trigger: Pointing ECC_ITO_CLI_EXECUTABLE at the package root, bin/ito.js (a source-level shim) instead of dist/bin/ito.js, a copied/renamed ito.js, or an out-directory like build/bin/ito.js.

Common situations: Operators 'simplifying' the path or symlinking a friendly name like ~/.local/bin/ito-cli (realpath resolves it, but the underlying path must still end in the canonical segments); custom fork builds writing to a different out dir.

Related errors


AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18). Data as JSON: /api/errors/71265d98b6a980c3. 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 06c5e118c4)