affaan-m/ECC · error

${option} is required exactly once for live node qualificati

Error message

${option} is required exactly once for live node qualification.

What it means

ito.js requires that --cluster, --nodes, and --config-dir each appear exactly once for live node qualification. requiredOptionValue counts occurrences and throws if the count is not exactly one (zero or duplicates). This enforces an unambiguous, deliberate configuration for a sensitive live operation.

Source

Thrown at scripts/ito.js:97

forward ITO_API_KEY directly when configured; ITO_AUTH_MODE=legacy is not
required. The canonical client stores device credentials in macOS Keychain by
default; file-token fallback remains explicit and must use restrictive settings.
Never put a key or token in arguments, tracked files, or chat.

Live node qualification requires ITO_ENABLE_SIXTYTWO_LIVE=1,
--live-sixtytwo, an explicit node list, and an existing absolute config
directory. It forwards only named SIXTYTWO_API_TOKEN/SIXTYTWO_TOKEN and SSH
agent state; ITO_API_KEY is intentionally excluded. The canonical CLI requires
sixtytwo-cli==0.3.33 and fails closed.
`);
}

function requiredOptionValue(args, option) {
  const indexes = args
    .map((value, index) => (value === option ? index : -1))
    .filter((index) => index >= 0);
  if (indexes.length !== 1) {
    throw new Error(`${option} is required exactly once for live node qualification.`);
  }
  const value = args[indexes[0] + 1];
  if (!value?.trim() || value.startsWith("--")) {
    throw new Error(`${option} requires a non-empty value for live node qualification.`);
  }
  return value;
}

function validateNodeQualificationArgs(args, environment) {
  if (environment.ITO_ENABLE_SIXTYTWO_LIVE !== "1") {
    throw new Error(
      "Live node qualification requires ITO_ENABLE_SIXTYTWO_LIVE=1 before any process is started."
    );
  }
  if (args.filter((value) => value === "--live-sixtytwo").length !== 1) {
    throw new Error(
      "Live node qualification requires --live-sixtytwo exactly once before any process is started."
    );

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Provide --cluster, --nodes, and --config-dir each exactly once
  2. Audit your wrapper for duplicate injection of any of these options
  3. Run with --help to confirm the required option set for live qualification

Example fix

// before
--live-sixtytwo --nodes n1 --config-dir /cfg
// after
--live-sixtytwo --cluster c1 --nodes n1 --config-dir /cfg
Defensive patterns

Strategy: validation

Validate before calling

function assertOptionExactlyOnce(args, option) {
  const count = args.filter(a => a === option).length;
  if (count !== 1) throw new Error(`${option} must appear exactly once (found ${count})`);
}
['--cluster','--nodes','--config-dir'].forEach(opt => assertOptionExactlyOnce(args, opt));

Type guard

function optionAppearsExactlyOnce(args, option) {
  return args.filter(a => a === option).length === 1;
}

Try / catch

try { validateNodeQualificationArgs(args, env); }
catch (err) {
  if (/is required exactly once/.test(err.message)) {
    console.error(err.message);
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Omitting --cluster entirely, or passing --cluster twice (e.g. once in a base command and once in an override), or any of the three required options appearing 0 or 2+ times.

Common situations: A wrapper script that always adds --cluster colliding with a user-supplied one, or forgetting one of the three required options when assembling the live-qualification command.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/ec7f763c0a6742de. Report an issue: GitHub.