affaan-m/ECC · error

Non-interactive and JSON mutations require --yes.

Error message

Non-interactive and JSON mutations require --yes.

What it means

Any non-interactive or --json run that would actually mutate the install must confirm intent with --yes (or be a --dry-run preview). Without --yes and without --dry-run, the installer refuses to proceed to prevent accidental mutations in CI/automation.

Source

Thrown at scripts/install-guided.js:198

  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);
    output.write(`${harness.label.padEnd(13)} ${entry.channel.padEnd(17)} ${harness.destination}\n`);
  }
  if (plan.request.harnesses.includes('kimi')) {
    output.write('\nKimi note: ECC hooks are not configured; model, provider, and authentication settings are unchanged.\n');
  }
}

async function confirmPlan(terminal, output) {
  output.write('\n');
  const answer = await terminal.question('Apply ECC to these harnesses? [y/N]: ');

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Add --yes to confirm the mutation in non-interactive/JSON mode
  2. Add --dry-run instead if you only want to preview the plan
  3. Run interactively (with a TTY) so confirmation can be prompted

Example fix

// before
node scripts/install-guided.js --harness claude --claude-scope user --claude-hooks standard
// after
node scripts/install-guided.js --harness claude --claude-scope user --claude-hooks standard --yes
Defensive patterns

Strategy: validation

Validate before calling

const interactive = process.stdin.isTTY === true;
const mutatingNonInteractive = (!interactive || argv.includes('--json'));
if (mutatingNonInteractive && !argv.includes('--yes') && !argv.includes('--dry-run')) {
  throw new Error('Add --yes (or --dry-run) for non-interactive/JSON mutations');
}

Type guard

function hasNonInteractiveConfirmation(argv) {
  return argv.includes('--yes') || argv.includes('-y') || argv.includes('--dry-run');
}

Try / catch

try { validateExecutionMode(options, interactive); }
catch (err) {
  if (/require --yes/.test(err.message)) {
    console.error(`${err.message} (or use --dry-run to preview)`);
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running install-guided.js in CI with all the right selections but forgetting --yes, or using --json without --yes.

Common situations: CI pipelines, Docker builds, or scripted setups where the author omitted --yes expecting a prompt that cannot appear.

Related errors


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