affaan-m/ECC · error · Error
Invalid Claude scope
Error message
Invalid Claude scope: ${claudeScope} What it means
normalizeGuidedInstallRequest validates the resolved claudeScope (defaulting to 'user' when Claude is selected and no value given) against the VALID_CLAUDE_SCOPES set. An unrecognized scope string throws this error with the offending value interpolated. It is a whitelist enum check on user-supplied configuration.
Solutions
- Use one of the valid Claude scopes (check VALID_CLAUDE_SCOPES in scripts/lib/multi-harness-setup.js, e.g. 'user' or 'project')
- Omit claudeScope entirely to get the default 'user' scope
- Trim/lowercase the value before passing it if it comes from user input
Example fix
// before
runSetup({ harnesses: ['claude'], claudeScope: 'global' })
// after
runSetup({ harnesses: ['claude'], claudeScope: 'user' }) Defensive patterns
Strategy: validation
Validate before calling
const VALID_SCOPES = ['user', 'project'] // confirm against VALID_CLAUDE_SCOPES in the library
if (input.claudeScope !== undefined && !VALID_SCOPES.includes(input.claudeScope)) {
throw new Error(`claudeScope must be one of: ${VALID_SCOPES.join(', ')}`)
} Type guard
const isValidScope = (s) => typeof s === 'string' && ['user', 'project'].includes(s)
Try / catch
try {
return normalizeGuidedInstallRequest(input)
} catch (err) {
if (err.message.startsWith('Invalid Claude scope:')) {
console.error(err.message, '— valid scopes:', [...VALID_CLAUDE_SCOPES])
return normalizeGuidedInstallRequest({ ...input, claudeScope: undefined })
}
throw err
} Prevention
- Import/derive valid values from the library's exported sets instead of hardcoding strings
- Use CLI choice lists restricted to valid scopes
- Normalize case/whitespace before passing user input
When it happens
Trigger: Calling the guided install request API with input.claudeScope set to a string not in VALID_CLAUDE_SCOPES (e.g. a typo like 'global', 'repo', or 'workspace' instead of a valid value such as 'user' or 'project').
Common situations: Typo in a script or CI config; copying a scope name from another tool with different vocabulary; casing mismatch ('Project' vs 'project').
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
- Install module has unsupported targets
- Invalid Kimi install profile
- application config exceeds local size limit
- artifact has invalid modality binding
- Asset request_id/modality does not match the bundle
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/91aefdac8d4ac9ba.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/multi-harness-setup.js:39
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)) {
throw new Error(`Invalid Claude hooks preference: ${claudeHooks}`);
}
if (profile && !VALID_PROFILES.has(profile)) {
throw new Error(`Invalid Kimi install profile: ${profile}`);
}
return {
harnesses,
...(claudeHooks ? { claudeHooks } : {}),
...(claudeScope ? { claudeScope } : {}),
dryRun: Boolean(input.dryRun),
json: Boolean(input.json),
...(profile ? { profile } : {}),
yes: Boolean(input.yes),
};
}View on GitHub (pinned to 8321021c54)