{"record":{"id":"f12d3720bf6e131e","repo":"affaan-m/ECC","slug":"refusing-unverified-ownership-from-install-state-a","errorCode":null,"errorMessage":"Refusing unverified ownership from install-state at ${plan.installStatePath}: operation identity does not match the current plan for ${destinationPath}.","messagePattern":"Refusing unverified ownership from install-state at (.+?): operation identity does not match the current plan for (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":216,"sourceCode":"  assertPriorInstallStateMatchesPlan(state, plan);\n  const plannedByDestination = new Map(plan.operations.map(operation => [\n    canonicalPath(operation.destinationPath),\n    operation,\n  ]));\n  const destinations = new Set();\n  for (const operation of state.operations || []) {\n    if (operation.ownership !== 'managed') {\n      throw new Error(\n        `Refusing to trust non-managed ownership from install-state at ${plan.installStatePath}.`\n      );\n    }\n    const destinationPath = operation.destinationPath;\n    assertWithinTrustedRoot(destinationPath, plan.targetRoot, 'trust install-state ownership');\n    const canonicalDestination = canonicalPath(destinationPath);\n    const plannedOperation = plannedByDestination.get(canonicalDestination);\n    if (!plannedOperation) continue;\n    if (!operationIdentityMatches(operation, plannedOperation)) {\n      throw new Error(\n        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `\n        + `operation identity does not match the current plan for ${destinationPath}.`\n      );\n    }\n    const currentFingerprint = fingerprintFile(destinationPath);\n    if (\n      !currentFingerprint.exists\n      || !/^[a-f0-9]{64}$/i.test(operation.contentSha256 || '')\n      || currentFingerprint.sha256 !== operation.contentSha256.toLowerCase()\n    ) {\n      throw new Error(\n        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `\n        + `content digest does not match ${destinationPath}.`\n      );\n    }\n    destinations.add(canonicalDestination);\n  }\n  return { destinations, stateFingerprint: validatedFingerprint };","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/multi-harness-setup.js#L198-L234","documentation":"For each state operation that also appears in the current plan, operationIdentityMatches compares kind, moduleId, sourceRelativePath, strategy, and scaffoldOnly. If any field differs, the recorded ownership no longer corresponds to what the plan intends to write there, so the ownership claim is rejected with this error. This prevents stale state from authorizing a changed operation over an existing file.","triggerScenarios":"A destination path exists in both state.operations and plan.operations but with a different kind/moduleId/sourceRelativePath/strategy/scaffoldOnly — e.g. the plan was regenerated after ECC updated the module's file layout, or the state was recorded by a different version of ECC.","commonSituations":"Upgrading ECC to a version that changed a file's kind (copy-file vs merge-json) or source path; state file left over from an older install while the plan was rebuilt; moduleId renamed in the plugin.","solutions":["Delete the stale install-state file and re-run the guided install so state and plan are generated together.","Align plan and state versions: re-run preview/plan generation from the installed ECC version instead of mixing old state with a new plan.","Verify no old state file from a previous ECC version is being read (check installStatePath); remove legacy state."],"exampleFix":"// before: old state says copy-file, new plan says merge-json for same path\n// after: regenerate state\nfs.rmSync(plan.installStatePath);\nconst freshPlan = buildPlan(adapter); // state recreated with matching identities","handlingStrategy":"validation","validationCode":"for (const op of plan.operations) {\n  const recorded = state.operations.find(s => s.destinationPath === op.destinationPath);\n  if (recorded && ['kind','moduleId','sourceRelativePath','strategy','scaffoldOnly'].some(f => recorded[f] !== op[f])) {\n    throw new Error(`Identity mismatch at ${op.destinationPath}; regenerate install-state.`);\n  }\n}","typeGuard":"function identitiesMatch(stateOp, planOp) {\n  return ['kind','moduleId','sourceRelativePath','strategy','scaffoldOnly'].every(f => stateOp?.[f] === planOp?.[f]);\n}","tryCatchPattern":"try {\n  readOwnedDestinations(plan, deps);\n} catch (err) {\n  if (String(err.message).includes('operation identity does not match')) {\n    fs.rmSync(plan.installStatePath); // stale state from another version; regenerate\n  } else throw err;\n}","preventionTips":["Regenerate install-state whenever you upgrade ECC.","Do not mix a state file from one ECC version with a plan from another.","Run the guided preview so plan and state are produced together.","Check ECC version recorded alongside state before reusing it."],"tags":["install-state","identity-mismatch","upgrade"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}