affaan-m/ECC · error
Unknown guided harness selection
Error message
Unknown guided harness selection: ${token} What it means
normalizeHarnessSelection() in scripts/lib/harness-capabilities.js validates user-supplied harness tokens for guided workflows. Each token is either a 1-based menu number or a harness id; it is resolved against listGuidedHarnesses()/getHarnessCapability(). If no harness matches, the function throws 'Unknown guided harness selection' because a guided run must only ever operate on known, guided-capable harnesses.
Solutions
- Check the token spelling against the ids/names exported by harness-capabilities (list of guided harnesses).
- If using a number, use a 1-based index within the guided harness menu (1..listGuidedHarnesses().length).
- If the harness is advanced (not guided-ready), use the non-guided workflow or pass a guided-ready harness instead.
- If a recent upgrade renamed harnesses, update stored config/scripts to the new ids.
Example fix
// before
normalizeHarnessSelection(['claude-codee']); // typo -> throws
// after
const { listGuidedHarnesses } = require('./scripts/lib/harness-capabilities');
const ids = listGuidedHarnesses().map(h => h.id);
const wanted = ['claude-codee'];
normalizeHarnessSelection(wanted.filter(id => ids.includes(id))); Defensive patterns
Strategy: validation
Validate before calling
const { listGuidedHarnesses } = require('./scripts/lib/harness-capabilities');
function isValidHarnessToken(token) {
const idx = /^\d+$/.test(token) ? Number(token) - 1 : -1;
const guided = listGuidedHarnesses();
return idx >= 0 && idx < guided.length || guided.some(h => h.id === token);
}
const tokens = ['claude-code'];
if (!tokens.every(isValidHarnessToken)) throw new Error('invalid harness token'); Type guard
function isGuidedHarness(h) { return h != null && typeof h.id === 'string' && h.guidedReady === true; } Try / catch
try {
const ids = normalizeHarnessSelection(tokens);
} catch (err) {
if (String(err.message).startsWith('Unknown guided harness selection')) {
console.error(`Bad harness token: ${err.message}. Valid: ${listGuidedHarnesses().map(h => h.id).join(', ')}`);
} else throw err;
} Prevention
- Source tokens from listGuidedHarnesses().map(h => h.id) rather than hardcoding strings.
- Remember menu indices are 1-based, not 0-based.
- Validate any stored harness config after upgrading ECC versions.
- Keep the guided harness list visible in interactive prompts to reduce typos.
When it happens
Trigger: Calling normalizeHarnessSelection with a token that is neither a valid 1-based menu index (e.g. '0', '99', non-numeric junk) nor a recognized harness id/name (e.g. typo 'claude-codee', or an advanced harness id that getHarnessCapability does resolve — that hits error 231 instead, but an unregistered id hits this one). Exposed through askHarnesses, normalizedHarnesses, selectedHarnessIds, harnesses, and runTests.
Common situations: Typos when passing --harness style flags from scripts or CI; passing a numeric index of 0 or one past the end of the guided menu; stale config files naming a harness that was renamed or removed in a newer ECC version; passing an advanced (non-guided) harness that is not in the guided list.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 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/ad9364d94c93b820.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/harness-capabilities.js:352
const allTokens = tokens.filter(token => ['all', '*'].includes(normalizeLookupToken(token)));
const explicitTokens = tokens.filter(token => !['all', '*'].includes(normalizeLookupToken(token)));
if (allTokens.length > 0 && explicitTokens.length > 0) {
throw new Error('The all/* harness selection cannot be combined with other selections');
}
if (allTokens.length > 0) {
return GUIDED_HARNESS_IDS.slice();
}
const selected = new Set();
for (const token of tokens) {
const normalizedToken = normalizeLookupToken(token);
const menuIndex = /^\d+$/.test(normalizedToken) ? Number(normalizedToken) - 1 : -1;
const harness = menuIndex >= 0
? listGuidedHarnesses()[menuIndex] || null
: getHarnessCapability(token);
if (!harness) {
throw new Error(`Unknown guided harness selection: ${token}`);
}
if (!harness.guidedReady) {
throw new Error(`${harness.label} is an advanced harness and is not guided-ready`);
}
selected.add(harness.id);
}
if (selected.size === 0) {
throw new Error('At least one guided harness must be selected');
}
return GUIDED_HARNESS_IDS.filter(id => selected.has(id));
}
module.exports = {
GUIDED_HARNESS_IDS,
HARNESS_CAPABILITIES,
getHarnessCapability,View on GitHub (pinned to 8321021c54)