{"record":{"id":"a83a8b2f86328adf","repo":"affaan-m/ECC","slug":"managed-claude-install-state-is-invalid-at-state","errorCode":null,"errorMessage":"Managed Claude install-state is invalid at ${statePath}","messagePattern":"Managed Claude install-state is invalid at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install/inventory.js","lineNumber":80,"sourceCode":"      };\n    }\n  }\n  return null;\n}\n\nfunction validateManagedState(state, statePath, expectedRoot) {\n  const selectedModules = state?.resolution?.selectedModules;\n  const operations = state?.operations;\n  if (\n    state?.schemaVersion !== 'ecc.install.v1'\n    || !state.target\n    || typeof state.target !== 'object'\n    || Array.isArray(state.target)\n    || !Array.isArray(selectedModules)\n    || !selectedModules.every(moduleId => typeof moduleId === 'string' && moduleId.length > 0)\n    || !Array.isArray(operations)\n  ) {\n    throw new Error(`Managed Claude install-state is invalid at ${statePath}`);\n  }\n\n  for (const operation of operations) {\n    if (\n      !operation\n      || typeof operation !== 'object'\n      || typeof operation.destinationPath !== 'string'\n      || !path.isAbsolute(operation.destinationPath)\n      || !isWithinRoot(operation.destinationPath, expectedRoot)\n    ) {\n      throw new Error(`Managed Claude install-state is invalid at ${statePath}`);\n    }\n  }\n\n  return { selectedModules, operations };\n}\n\nfunction operationOverlapsPlugin(operation, expectedRoot) {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/install/inventory.js#L62-L98","documentation":"Thrown by validateManagedState in scripts/lib/install/inventory.js (two throw sites: structural check at line 80, per-operation check at line 91). The structural check requires state.schemaVersion === 'ecc.install.v1', state.target to be a non-array object, state.resolution.selectedModules to be an array of non-empty strings, and state.operations to be an array. The per-operation check requires each operation to be an object with an absolute destinationPath that isWithinRoot(expectedRoot). The expectedRoot confinement is security-critical: install-state is project-local and therefore attacker-controllable, so a state file that records a write outside the trusted root is treated as invalid rather than honored (see the GHSA note in path-safety.js).","triggerScenarios":"An install-state.json with a wrong/missing schemaVersion, missing or non-object target, malformed selectedModules (non-strings, empties, or not an array), or any operation whose destinationPath is relative or resolves outside the adapter-derived expectedRoot.","commonSituations":"An old install-state from a previous ECC schema version; a tampered state file (security-relevant — the containment check blocks malicious state from triggering writes outside the root); a hand-edited file; cross-platform path differences (relative vs absolute).","solutions":["Read the file at statePath and check schemaVersion first — it must be exactly 'ecc.install.v1'.","Verify state.target is an object, state.resolution.selectedModules is an array of non-empty strings, and state.operations is an array.","Verify every operations[].destinationPath is absolute and resolves within expectedRoot (the .claude dir or project .claude dir).","If the file is from an older ECC version, back it up and remove it, then reinstall.","If any destinationPath is outside the root, treat it as a potential tampering signal and audit the source of the state file before deleting."],"exampleFix":"// before (install-state.json)\n{ \"schemaVersion\": \"ecc.install.v0\", \"target\": {}, \"operations\": [] }\n\n// after\n{\n  \"schemaVersion\": \"ecc.install.v1\",\n  \"target\": { \"id\": \"claude\" },\n  \"resolution\": { \"selectedModules\": [\"core\"] },\n  \"operations\": []\n}","handlingStrategy":"validation","validationCode":"function looksLikeValidState(s, expectedRoot) {\n  if (!s || s.schemaVersion !== 'ecc.install.v1') return false;\n  if (!s.target || typeof s.target !== 'object' || Array.isArray(s.target)) return false;\n  if (!Array.isArray(s.resolution?.selectedModules)) return false;\n  if (!s.resolution.selectedModules.every(m => typeof m === 'string' && m.length > 0)) return false;\n  if (!Array.isArray(s.operations)) return false;\n  const { isWithinRoot } = require('../path-safety');\n  return s.operations.every(o =>\n    o && typeof o === 'object'\n    && typeof o.destinationPath === 'string'\n    && path.isAbsolute(o.destinationPath)\n    && isWithinRoot(o.destinationPath, expectedRoot)\n  );\n}\nif (!looksLikeValidState(state, expectedRoot)) {\n  throw new Error(`State at ${statePath} is structurally invalid or contains out-of-root operations`);\n}","typeGuard":"function isManagedState(v, expectedRoot) {\n  const { isWithinRoot } = require('../path-safety');\n  return Boolean(\n    v && v.schemaVersion === 'ecc.install.v1'\n    && v.target && typeof v.target === 'object' && !Array.isArray(v.target)\n    && Array.isArray(v.resolution?.selectedModules)\n    && v.resolution.selectedModules.every(m => typeof m === 'string' && m.length > 0)\n    && Array.isArray(v.operations)\n    && v.operations.every(o => o && typeof o === 'object'\n      && typeof o.destinationPath === 'string'\n      && path.isAbsolute(o.destinationPath)\n      && isWithinRoot(o.destinationPath, expectedRoot))\n  );\n}","tryCatchPattern":"try {\n  findManagedClaudeInstalls();\n} catch (err) {\n  if (/Managed Claude install-state is invalid/.test(err.message)) {\n    console.error('State file is structurally invalid or tampered — audit and reinstall.');\n  }\n  throw err;\n}","preventionTips":["Never manually edit install-state.json.","Upgrade ECC in lockstep with reinstalling so the state schema matches.","Treat any operation whose destinationPath resolves outside the adapter root as a security incident — audit the source of the state file.","Remove partial state files after a crashed install before retrying."],"tags":["install-state","validation","security","schema"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}