{"record":{"id":"a407012f3abd721f","repo":"affaan-m/ECC","slug":"refusing-to-overwrite-an-unowned-or-changed-instal","errorCode":null,"errorMessage":"Refusing to overwrite an unowned or changed install-state at ${plan.installStatePath}. Re-run the guided preview and review the existing state before retrying.","messagePattern":"Refusing to overwrite an unowned or changed install-state at (.+?)\\. Re-run the guided preview and review the existing state before retrying\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":91,"sourceCode":"}\n\nfunction operationIdentityMatches(stateOperation, plannedOperation) {\n  return [\n    'kind',\n    'moduleId',\n    'sourceRelativePath',\n    'strategy',\n    'scaffoldOnly',\n  ].every(field => stateOperation[field] === plannedOperation[field]);\n}\n\nfunction assertInstallStateUnchanged(plan, expectedFingerprint) {\n  const currentFingerprint = fingerprintFile(plan.installStatePath);\n  if (\n    currentFingerprint.exists !== expectedFingerprint.exists\n    || currentFingerprint.sha256 !== expectedFingerprint.sha256\n  ) {\n    throw new Error(\n      `Refusing to overwrite an unowned or changed install-state at ${plan.installStatePath}. `\n      + 'Re-run the guided preview and review the existing state before retrying.'\n    );\n  }\n}\n\nfunction assertPriorInstallStateMatchesPlan(state, plan) {\n  const target = state.target || {};\n  const adapter = plan.adapter || {};\n  if (\n    target.id !== adapter.id\n    || target.target !== adapter.target\n    || target.kind !== adapter.kind\n  ) {\n    throw new Error(\n      `Refusing to trust managed install-state at ${plan.installStatePath}: `\n      + 'target identity does not match the current Kimi install plan.'\n    );","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/multi-harness-setup.js#L73-L109","documentation":"Thrown by assertInstallStateUnchanged when the managed install-state file (plan.installStatePath) no longer matches the SHA-256 fingerprint captured during preflight. The installer fingerprints the state file before planning and re-checks it immediately before each write (beforeOperationWrite and beforeInstallStateWrite), refusing to proceed if the bytes changed in between. This is a deliberate TOCTOU (time-of-check/time-of-use) guard: the install-state is the sole proof of which destinations ECC owns, so silently overwriting a mutated state could clobber files the user edited.","triggerScenarios":"Called inside applyPreflightedManagedPlan via assertStateUnchanged() at beforeOperationWrite and beforeInstallStateWrite. Fires when fingerprintFile(plan.installStatePath) returns exists/sha256 differing from preview.ownershipSnapshot.stateFingerprint. This happens if, between createMultiHarnessPlan->preflightManaged and applyMultiHarnessPlan->applyManaged, the install-state JSON was edited, deleted, rewritten by another ECC process, touched by a sync tool (Dropbox/iCloud/git checkout), or the path started returning a different realpath.","commonSituations":"Running two guided installs concurrently in the same project; a previous partial install left a half-written state; the user hand-edited .claude/install-state.json; a git branch switch or filesystem sync changed the file between preview and apply; symlinks resolving differently between runs.","solutions":["Re-run the guided preview (createMultiHarnessPlan with dryRun) to regenerate the fingerprint against the current state, then apply immediately without touching the file.","If the existing install-state is stale or corrupt, delete plan.installStatePath and re-run the preview so ECC records fresh ownership.","Ensure no other ECC/install process, editor, or sync agent is touching the install-state between preview and apply.","Inspect the file at plan.installStatePath to confirm whether the change was intentional before discarding it."],"exampleFix":"// before: preview and apply separated by manual state edits\nconst preview = await createMultiHarnessPlan(req, {}, opts);\n// user edits .claude/install-state.json here -> fingerprint drifts\nawait applyMultiHarnessPlan(preview, {}, opts); // throws [280]\n\n// after: preview and apply back-to-back, no intervening mutation\nconst preview = await createMultiHarnessPlan(req, {}, opts);\nawait applyMultiHarnessPlan(preview, {}, opts);","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction assertInstallStateStable(installStatePath, expectedFingerprint) {\n  if (!installStatePath || !expectedFingerprint) return; // fresh install, nothing to check\n  const exists = fs.existsSync(installStatePath);\n  if (exists !== expectedFingerprint.exists) {\n    throw new Error(`Install-state existence changed; re-run preview before apply.`);\n  }\n  if (exists) {\n    const crypto = require('crypto');\n    const sha = crypto.createHash('sha256').update(fs.readFileSync(installStatePath)).digest('hex');\n    if (sha !== expectedFingerprint.sha256) {\n      throw new Error(`Install-state digest drift; re-run preview before apply.`);\n    }\n  }\n}\n// call right before applyMultiHarnessPlan:\nassertInstallStateStable(preview.harnesses.find(h=>h.id==='kimi').preview.plan.installStatePath,\n  preview.harnesses.find(h=>h.id==='kimi').preview.ownershipSnapshot.stateFingerprint);","typeGuard":"null","tryCatchPattern":"try {\n  await applyMultiHarnessPlan(preview, {}, options);\n} catch (err) {\n  if (/Refusing to overwrite an unowned or changed install-state/.test(err.message)) {\n    // state drifted between preview and apply: re-preflight and retry once\n    const repreview = await createMultiHarnessPlan(preview.request, {}, options);\n    await applyMultiHarnessPlan(repreview, {}, options);\n  } else throw err;\n}","preventionTips":["Run createMultiHarnessPlan and applyMultiHarnessPlan back-to-back with no filesystem mutation in between.","Treat the install-state file as append-only by ECC; never edit it manually.","Avoid running two installs against the same project concurrently.","Pause cloud-sync and close editors with the install-state open during install."],"tags":["install-state","toctou","fingerprint","multi-harness","kimi"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}