affaan-m/ECC · error · Error

Refusing unverified ownership from install-state at

Error message

Refusing unverified ownership from install-state at ${plan.installStatePath}: operation identity does not match the current plan for ${destinationPath}.

What it means

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.

Solutions

  1. Delete the stale install-state file and re-run the guided install so state and plan are generated together.
  2. Align plan and state versions: re-run preview/plan generation from the installed ECC version instead of mixing old state with a new plan.
  3. Verify no old state file from a previous ECC version is being read (check installStatePath); remove legacy state.

Example fix

// before: old state says copy-file, new plan says merge-json for same path
// after: regenerate state
fs.rmSync(plan.installStatePath);
const freshPlan = buildPlan(adapter); // state recreated with matching identities
Defensive patterns

Strategy: validation

Validate before calling

for (const op of plan.operations) {
  const recorded = state.operations.find(s => s.destinationPath === op.destinationPath);
  if (recorded && ['kind','moduleId','sourceRelativePath','strategy','scaffoldOnly'].some(f => recorded[f] !== op[f])) {
    throw new Error(`Identity mismatch at ${op.destinationPath}; regenerate install-state.`);
  }
}

Type guard

function identitiesMatch(stateOp, planOp) {
  return ['kind','moduleId','sourceRelativePath','strategy','scaffoldOnly'].every(f => stateOp?.[f] === planOp?.[f]);
}

Try / catch

try {
  readOwnedDestinations(plan, deps);
} catch (err) {
  if (String(err.message).includes('operation identity does not match')) {
    fs.rmSync(plan.installStatePath); // stale state from another version; regenerate
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/f12d3720bf6e131e. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/multi-harness-setup.js:216

  assertPriorInstallStateMatchesPlan(state, plan);
  const plannedByDestination = new Map(plan.operations.map(operation => [
    canonicalPath(operation.destinationPath),
    operation,
  ]));
  const destinations = new Set();
  for (const operation of state.operations || []) {
    if (operation.ownership !== 'managed') {
      throw new Error(
        `Refusing to trust non-managed ownership from install-state at ${plan.installStatePath}.`
      );
    }
    const destinationPath = operation.destinationPath;
    assertWithinTrustedRoot(destinationPath, plan.targetRoot, 'trust install-state ownership');
    const canonicalDestination = canonicalPath(destinationPath);
    const plannedOperation = plannedByDestination.get(canonicalDestination);
    if (!plannedOperation) continue;
    if (!operationIdentityMatches(operation, plannedOperation)) {
      throw new Error(
        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `
        + `operation identity does not match the current plan for ${destinationPath}.`
      );
    }
    const currentFingerprint = fingerprintFile(destinationPath);
    if (
      !currentFingerprint.exists
      || !/^[a-f0-9]{64}$/i.test(operation.contentSha256 || '')
      || currentFingerprint.sha256 !== operation.contentSha256.toLowerCase()
    ) {
      throw new Error(
        `Refusing unverified ownership from install-state at ${plan.installStatePath}: `
        + `content digest does not match ${destinationPath}.`
      );
    }
    destinations.add(canonicalDestination);
  }
  return { destinations, stateFingerprint: validatedFingerprint };

View on GitHub (pinned to 8321021c54)