affaan-m/ECC · error
Managed Claude install-state is invalid at
Error message
Managed Claude install-state is invalid at ${statePath} What it means
validateManagedState() checks the shape of the managed Claude install-state file read from statePath. It requires a target object and arrays of non-empty-string selectedModules and operations; when that top-level shape fails it throws this error. This protects subsequent install/update logic from corrupted or hand-mangled state.
Solutions
- Inspect the state file at statePath and restore the required shape: an object with target (object), selectedModules (array of non-empty strings), and operations (array).
- Restore the file from version control/backup if it is tracked, or from a backup of your config directory.
- Delete the corrupted state file and re-run the install so ECC regenerates valid state.
- If you migrated from an older ECC version, re-run the installer to rewrite state in the current format.
Example fix
// before (state.json)
{ "target": "~/.claude", "selectedModules": "agents" }
// after
{ "target": { "configDir": "/home/me/.claude" }, "selectedModules": ["agents"], "operations": [] } Defensive patterns
Strategy: validation
Validate before calling
const state = JSON.parse(fs.readFileSync(statePath, 'utf8'));
const ok = state && typeof state === 'object'
&& typeof state.target === 'object' && state.target !== null && !Array.isArray(state.target)
&& Array.isArray(state.selectedModules)
&& state.selectedModules.every(m => typeof m === 'string' && m.length > 0)
&& Array.isArray(state.operations);
if (!ok) throw new Error(`State shape invalid before call: ${statePath}`); Type guard
function hasValidStateShape(state) {
return !!state && typeof state === 'object' && !Array.isArray(state)
&& typeof state.target === 'object' && state.target !== null && !Array.isArray(state.target)
&& Array.isArray(state.selectedModules)
&& state.selectedModules.every(m => typeof m === 'string' && m.length > 0)
&& Array.isArray(state.operations);
} Try / catch
try {
validateManagedState(statePath);
} catch (err) {
if (err.message.startsWith('Managed Claude install-state is invalid')) {
console.error(`${statePath} failed shape validation — restore or re-install`);
process.exitCode = 1;
} else throw err;
} Prevention
- Treat install-state as machine-managed: edit through installer commands, not by hand.
- Back up the state file before upgrades or migrations.
- After an interrupted install, re-run the installer instead of salvaging partial state.
- Version-check state format when syncing config directories between machines.
When it happens
Trigger: A state file at statePath missing required fields (target, selectedModules, operations), with selectedModules containing non-string or empty-string entries, or with any of the three fields the wrong type (e.g. operations as an object); the file was truncated or manually edited.
Common situations: Manual cleanup of ~/.claude state deleting fields; interrupted install leaving a partially written state; an older ECC state format no longer matching the current validator; syncing dotfiles with a stale/different version of the state file.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Invalid install-state
- Invalid : expected a non-empty JSON object
- Work item is already done; cannot claim.
- -32602
- a claim token is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/a83a8b2f86328adf.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install/inventory.js:80
};
}
}
return null;
}
function validateManagedState(state, statePath, expectedRoot) {
const selectedModules = state?.resolution?.selectedModules;
const operations = state?.operations;
if (
state?.schemaVersion !== 'ecc.install.v1'
|| !state.target
|| typeof state.target !== 'object'
|| Array.isArray(state.target)
|| !Array.isArray(selectedModules)
|| !selectedModules.every(moduleId => typeof moduleId === 'string' && moduleId.length > 0)
|| !Array.isArray(operations)
) {
throw new Error(`Managed Claude install-state is invalid at ${statePath}`);
}
for (const operation of operations) {
if (
!operation
|| typeof operation !== 'object'
|| typeof operation.destinationPath !== 'string'
|| !path.isAbsolute(operation.destinationPath)
|| !isWithinRoot(operation.destinationPath, expectedRoot)
) {
throw new Error(`Managed Claude install-state is invalid at ${statePath}`);
}
}
return { selectedModules, operations };
}
function operationOverlapsPlugin(operation, expectedRoot) {View on GitHub (pinned to 8321021c54)