affaan-m/ECC · error
Invalid . : expected an array
Error message
Invalid ${label}.${event}: expected an array What it means
After confirming the event name is valid, validateManagedHooks requires the value under each event key to be an array of hook entries. This error fires when the value is any other type (object, string, number, null, undefined). It protects the later per-entry validation from operating on a non-iterable/mis-shaped value.
Solutions
- Wrap the hook entries in an array under the offending event key.
- Re-read the error text: label.event identifies exactly which key has the wrong shape.
- Re-run the ECC installer to regenerate the managed-hooks block rather than hand-merging old settings.json content.
- Validate the shape with Array.isArray before calling the API.
Example fix
// before
const hooks = { PreToolUse: { id: 'fmt', matcher: 'Bash', hooks: [{ type: 'command', command: 'fmt' }] } };
// after
const hooks = { PreToolUse: [{ id: 'fmt', matcher: 'Bash', hooks: [{ type: 'command', command: 'fmt' }] }] }; Defensive patterns
Strategy: type-guard
Validate before calling
for (const [event, entries] of Object.entries(managedHooks)) {
if (!Array.isArray(entries)) throw new Error(`hooks.${event} must be an array`);
} Type guard
function isHooksMap(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v)
&& Object.values(v).every(Array.isArray);
} Try / catch
try {
validateManagedHooks(hooks);
} catch (err) {
if (/expected an array/.test(err.message)) {
const event = err.message.match(/\.(\w+):/)?.[1];
if (event && !Array.isArray(hooks[event])) hooks[event] = [hooks[event]];
}
throw err;
} Prevention
- Always wrap entries in arrays, even for a single hook
- Normalize configs through a builder function that guarantees arrays
- Run Array.isArray checks on parsed JSON before passing to the API
- Beware JSON round-trips: single objects stay objects unless wrapped
When it happens
Trigger: Passing a hooks map where an event maps to something other than an array, e.g. { PreToolUse: { id: 'x', ... } } (single entry not wrapped in an array) or { Stop: 'lint.sh' }.
Common situations: Hand-merging two hook configs and dropping the array wrapper; JSON with a single object instead of a list under an event; a schema change in an older ECC version whose persisted format used objects per event.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Invalid managed hook entry at
- Invalid managed hook entry at
- Invalid managed hook handler at
- Canonical session snapshot must be an object
- Canonical session snapshot requires
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/f22a9861784741b2.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install/claude-settings.js:141
throw new Error(`Invalid managed hook handler at ${label}: invalid model`);
}
}
function validateManagedHooks(managedHooks, label = 'managed hooks') {
if (!isJsonObject(managedHooks)) {
throw new Error(`Invalid ${label}: expected a JSON object`);
}
if (Object.keys(managedHooks).length === 0) {
throw new Error(`Invalid ${label}: expected at least one hook event`);
}
const seenIds = new Set();
for (const [event, entries] of Object.entries(managedHooks)) {
if (!VALID_EVENTS.has(event)) {
throw new Error(`Invalid ${label}: unsupported hook event "${event}"`);
}
if (!Array.isArray(entries)) {
throw new Error(`Invalid ${label}.${event}: expected an array`);
}
if (entries.length === 0) {
throw new Error(`Invalid ${label}.${event}: expected at least one hook entry`);
}
entries.forEach((entry, index) => {
if (!isJsonObject(entry)) {
throw new Error(
`Invalid managed hook entry at ${label}.${event}[${index}]: expected a JSON object`
);
}
if (typeof entry.id !== 'string' || entry.id.trim() === '') {
throw new Error(
`Invalid managed hook entry at ${label}.${event}[${index}]: `
+ 'expected a non-empty unique id'
);
}
if (seenIds.has(entry.id)) {View on GitHub (pinned to 8321021c54)