{"record":{"id":"dd3536e4cf400242","repo":"affaan-m/ECC","slug":"refusing-to-trust-install-state-that-changed-durin","errorCode":null,"errorMessage":"Refusing to trust install-state that changed during validation: ${plan.installStatePath}.","messagePattern":"Refusing to trust install-state that changed during validation: (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/multi-harness-setup.js","lineNumber":194,"sourceCode":"    return { destinations: new Set(), stateFingerprint: { exists: false, sha256: null } };\n  }\n  try {\n    assertSafeInstallOperation(plan, { destinationPath: plan.installStatePath });\n  } catch (error) {\n    throw new Error(`Refusing to trust managed install-state path: ${error.message}`);\n  }\n  const initialFingerprint = fingerprintFile(plan.installStatePath);\n  if (!initialFingerprint.exists) {\n    return { destinations: new Set(), stateFingerprint: { exists: false, sha256: null } };\n  }\n  const readState = dependencies.readInstallState || require('./install-state').readInstallState;\n  const state = readState(plan.installStatePath);\n  const validatedFingerprint = fingerprintFile(plan.installStatePath);\n  if (\n    initialFingerprint.exists !== validatedFingerprint.exists\n    || initialFingerprint.sha256 !== validatedFingerprint.sha256\n  ) {\n    throw new Error(\n      `Refusing to trust install-state that changed during validation: ${plan.installStatePath}.`\n    );\n  }\n  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);","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/multi-harness-setup.js#L176-L212","documentation":"readOwnedDestinations fingerprints the install-state file (exists flag + sha256) before and after reading and validating it. If the two fingerprints differ, the file changed concurrently while being validated, so its contents cannot be trusted, and this error is thrown. This is a TOCTOU guard preventing a racing process or editor from swapping the state between read and verification.","triggerScenarios":"The install-state file is modified, replaced, or deleted between fingerprintFile() before readState() and the fingerprint taken after — e.g. a concurrent install/update process, an editor auto-save, or a sync tool (Dropbox/rsync) touching the file during install.","commonSituations":"Running two installs of ECC in parallel; a dotfile-sync service updating ~/.config while an install runs; a test or script regenerating install-state mid-run; VCS checkout/branch switch during install.","solutions":["Re-run the install once no other install/update process is active (ensure single-writer).","Pause file-sync tools or editors watching the target directory during install.","Delete the changed state file and re-run the guided install to rebuild a consistent state."],"exampleFix":"// before: two installs racing\nrunInstall(planA) && runInstall(planB); // second mutates state mid-validation\n// after: serialize installs\nawait runInstall(planA);\nawait runInstall(planB);","handlingStrategy":"retry","validationCode":"const before = fingerprintFile(plan.installStatePath);\n// ensure no concurrent writer before invoking\nif (isInstallRunning()) throw new Error('Another install is in progress');","typeGuard":"function isStateStable(fp1, fp2) {\n  return fp1.exists === fp2.exists && fp1.sha256 === fp2.sha256;\n}","tryCatchPattern":"try {\n  const owned = readOwnedDestinations(plan, deps);\n} catch (err) {\n  if (String(err.message).includes('changed during validation')) {\n    // wait and retry once with no concurrent processes\n    await waitForFileQuiet(plan.installStatePath);\n    return readOwnedDestinations(plan, deps);\n  }\n  throw err;\n}","preventionTips":["Run one install at a time; use a lock file for scripted installs.","Pause Dropbox/rsync/git operations on the target directory during install.","Avoid editors with auto-save watching the state directory during installs.","Retry the install once after the error; persistent instability means a background writer exists."],"tags":["race-condition","install-state","concurrency"],"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"}