affaan-m/ECC · error · Error
--nodes must explicitly list one or more non-empty nodes.
Error message
--nodes must explicitly list one or more non-empty nodes.
What it means
validateNodeQualificationArgs in scripts/ito.js validates the --nodes option for the `ecc ito evals` command. It throws this error when any comma-separated entry in --nodes is empty or whitespace-only, e.g. `--nodes a,,b` or a trailing comma. This guards node qualification from launching processes against an incomplete node list.
Solutions
- Provide a comma-separated list where every entry is a non-empty trimmed node name, e.g. --nodes node-a,node-b
- Strip trailing/leading commas and empty entries from the value before invoking the CLI
- If nodes come from a template or variable, validate the joined string with a check like list.split(',').every(n => n.trim()) first
Example fix
// before run(['--nodes', 'alpha,,beta']) // after run(['--nodes', 'alpha,beta'])
Defensive patterns
Strategy: validation
Validate before calling
function validateNodes(v) { return typeof v === 'string' && v.split(',').every(n => n.trim().length > 0); }
if (!validateNodes(nodes)) throw new Error('every --nodes entry must be non-empty'); Type guard
const isNodeList = (v) => typeof v === 'string' && v.length > 0 && v.split(',').every((n) => n.trim().length > 0); Try / catch
try {
runEccItoEvals(nodes);
} catch (e) {
if (e.message.includes('--nodes')) {
const cleaned = nodes.split(',').map(s => s.trim()).filter(Boolean).join(',');
retryWith(cleaned);
} else throw e;
} Prevention
- Normalize node lists (trim, drop empties) at the point where they are built
- Never template node lists from variables without validating the joined string
- Avoid hand-editing long comma lists; generate them programmatically
When it happens
Trigger: Running `ecc ito evals --live-sixtytwo ... --cluster X --nodes "a,,b"`, `--nodes ""`, `--nodes "a,"`, or `--nodes " a, , b"` — any split("\,") element whose trim() is empty.
Common situations: Manually editing a long node list and leaving a trailing comma; templating a node list where a variable expands empty; copy-pasting lists with stray spaces between commas.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- all overlays must be readable local files
- all takes must be readable local files
- Arguments must not contain NUL bytes.
- asset name must be a simple filename stem (letters, digits…
- At least one guided harness must be selected
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/8e4f920018bbd37f.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/ito.js:120
}
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."
);
}
requiredOptionValue(args, "--cluster");
const nodes = requiredOptionValue(args, "--nodes");
if (!nodes.split(",").every((node) => node.trim().length > 0)) {
throw new Error("--nodes must explicitly list one or more non-empty nodes.");
}
const configDirectory = requiredOptionValue(args, "--config-dir");
if (!path.isAbsolute(configDirectory)) {
throw new Error("--config-dir must be an existing absolute directory.");
}
try {
const resolved = fs.realpathSync.native(configDirectory);
if (
!fs.statSync(resolved).isDirectory()
|| !fs.statSync(path.join(resolved, "sixtytwo.yaml")).isFile()
) {
throw new Error("invalid qualification configuration");
}
} catch {
throw new Error(
"--config-dir must exist and contain a regular sixtytwo.yaml before any process is started."
);
}View on GitHub (pinned to 8321021c54)