affaan-m/ECC · error · Error
Non-interactive guided install requires at least one…
Error message
Non-interactive guided install requires at least one --harness.
What it means
validateExecutionMode() rejects non-interactive runs that select no harnesses. When stdin is not a TTY the script cannot ask which harnesses to install, so an explicit --harness list (or --all-harnesses) is mandatory. Without it there is nothing to install, so the script aborts before doing any work.
Solutions
- Add explicit --harness flags, e.g. --harness claude --harness codex.
- Or pass --all-harnesses to select every harness non-interactively.
- In CI, ensure the harness list variable is non-empty before invoking the script.
Example fix
// before (non-interactive) node scripts/install-guided.js --claude-scope project --claude-hooks standard --yes // after node scripts/install-guided.js --harness claude --claude-scope project --claude-hooks standard --yes
Defensive patterns
Strategy: validation
Validate before calling
if (!process.stdin.isTTY && harnessFlags.length === 0) { throw new Error('Non-interactive runs need --harness or --all-harnesses'); } Try / catch
try { await runInstall(args); } catch (e) { if (String(e.message).includes('requires at least one --harness')) { console.error('Add --harness <id> or --all-harnesses for non-interactive use'); process.exit(2); } throw e; } Prevention
- Always pass explicit --harness flags in CI and scripted contexts.
- Avoid accidental stdin redirection that flips the installer into non-interactive mode.
- Assert the harness list variable is non-empty before invoking.
When it happens
Trigger: Running the guided install non-interactively (piped stdin, CI, `</dev/null`) without any --harness flag, so selectedHarnessIds(options) returns an empty array.
Common situations: CI pipelines invoking the installer without harness flags; redirecting stdin accidentally (e.g. `install < file`) forcing non-interactive mode; wrapper scripts that drop --harness flags when variables are empty.
Understand the failure class
Background: "--flag is required" and "must specify" CLI errors: how missing-required-flag validation works and how to fix it — this error's family across 20 libraries.
Related errors
- Claude requires explicit --claude-scope and --claude-hooks…
- Kimi requires an explicit --profile choice in this mode.
- An executable is required after --.
- An install config path is required
- At least one --target is required for handoffs.
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/cc9ab92d70403aaf.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/install-guided.js:189
return {
...options,
harnesses: normalizedHarnesses,
claudeScope,
claudeHooks,
profile,
};
}
function selectedHarnessIds(options) {
if (options.allHarnesses) return normalizeHarnessSelection(['all']);
if (options.harnesses.length === 0) return [];
return normalizeHarnessSelection(options.harnesses);
}
function validateExecutionMode(options, interactive) {
const harnesses = selectedHarnessIds(options);
if (!interactive && harnesses.length === 0) {
throw new Error('Non-interactive guided install requires at least one --harness.');
}
const requiresExplicit = !interactive || options.json;
if (requiresExplicit && harnesses.includes('claude') && (!options.claudeScope || !options.claudeHooks)) {
throw new Error('Claude requires explicit --claude-scope and --claude-hooks choices in this mode.');
}
if (requiresExplicit && harnesses.includes('kimi') && !options.profile) {
throw new Error('Kimi requires an explicit --profile choice in this mode.');
}
if ((!interactive || options.json) && !options.yes && !options.dryRun) {
throw new Error('Non-interactive and JSON mutations require --yes.');
}
}
function printPlan(plan, output) {
output.write('\nECC guided install preview\n\n');
output.write('Harness Channel Destination\n');
for (const entry of plan.harnesses) {
const harness = getHarnessCapability(entry.id);View on GitHub (pinned to 8321021c54)