affaan-m/ECC · error · Error
Choose at least one guided harness: Claude, Codex, or Kimi.
Error message
Choose at least one guided harness: Claude, Codex, or Kimi.
What it means
normalizeGuidedInstallRequest validates the guided multi-harness install request. It normalizes the harnesses selection, and if the resulting list is empty it throws this error — a guided install must target at least one of the supported harnesses (Claude, Codex, Kimi).
Solutions
- Pass at least one supported harness, e.g. harnesses: ['claude'].
- Check spelling of harness names (claude, codex, kimi) — invalid entries are normalized away.
- If running the CLI, add the required harness flag/option to the command.
- Re-run the interactive flow and select at least one harness before confirming.
Example fix
// before
request({ harnesses: [] });
// after
request({ harnesses: ['claude', 'codex'] }); Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED = ['claude', 'codex', 'kimi'];
const harnesses = (input.harnesses || []).filter(h => SUPPORTED.includes(h));
if (harnesses.length === 0) throw new Error('Select at least one of: claude, codex, kimi.'); Type guard
const hasValidHarnessSelection = (input) => Array.isArray(input.harnesses) && input.harnesses.some(h => ['claude','codex','kimi'].includes(h));
Try / catch
try {
normalizeGuidedInstallRequest(input);
} catch (err) {
if (err.message.includes('Choose at least one guided harness')) {
// prompt the user again or default to ['claude']
} else throw err;
} Prevention
- Always pass a non-empty harnesses array to guided install requests.
- Validate harness names against the supported list before submitting.
- In interactive flows, require at least one selection before submit.
- Keep harness names lowercase and exact (claude, codex, kimi).
When it happens
Trigger: Invoking the guided setup/request path with harnesses omitted, an empty array, or a list whose entries all fail normalization (invalid names dropped) — e.g. input.harnesses = [] or input.harnesses = ['cursor'] (unsupported in guided mode).
Common situations: CLI invocation missing the harness flag; config file with a misspelled harness name that normalizes away; interactive flow where the user unchecked every option before submitting.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 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/bce964a1bad8f6ef.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/multi-harness-setup.js:23
const os = require('os');
const path = require('path');
const { assertSafeInstallOperation } = require('./install/apply');
const { assertWithinTrustedRoot, realpathNearestExisting } = require('./path-safety');
const VALID_CLAUDE_SCOPES = new Set(['user', 'project', 'local']);
const VALID_CLAUDE_HOOKS = new Set(['off', 'minimal', 'standard', 'strict']);
const VALID_PROFILES = new Set(['minimal', 'core', 'developer', 'security', 'research', 'full']);
function catalogHelpers() {
return require('./harness-capabilities');
}
function normalizeGuidedInstallRequest(input = {}) {
const { normalizeHarnessSelection } = catalogHelpers();
const harnesses = normalizeHarnessSelection(input.harnesses || []);
if (harnesses.length === 0) {
throw new Error('Choose at least one guided harness: Claude, Codex, or Kimi.');
}
const includesClaude = harnesses.includes('claude');
const includesKimi = harnesses.includes('kimi');
if (!includesClaude && (input.claudeScope !== undefined || input.claudeHooks !== undefined)) {
throw new Error('Claude scope and hook options require Claude to be selected.');
}
if (!includesKimi && input.profile !== undefined) {
throw new Error('The managed install profile requires Kimi to be selected.');
}
const claudeScope = includesClaude ? (input.claudeScope || 'user') : undefined;
const claudeHooks = includesClaude ? (input.claudeHooks || 'standard') : undefined;
const profile = includesKimi ? (input.profile || 'core') : undefined;
if (claudeScope && !VALID_CLAUDE_SCOPES.has(claudeScope)) {
throw new Error(`Invalid Claude scope: ${claudeScope}`);
}
if (claudeHooks && !VALID_CLAUDE_HOOKS.has(claudeHooks)) {View on GitHub (pinned to 8321021c54)