{"record":{"id":"5ce4edb967a772f4","repo":"affaan-m/ECC","slug":"missing-source-file-for-repair-sourcepath-op","errorCode":null,"errorMessage":"Missing source file for repair: ${sourcePath || operation.sourceRelativePath}","messagePattern":"Missing source file for repair: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/install-lifecycle.js","lineNumber":734,"sourceCode":"      }\n    }\n\n    return Object.keys(nextValue).length === 0 ? JSON_REMOVE_SENTINEL : nextValue;\n  }\n\n  if (Array.isArray(managedValue)) {\n    return jsonContainsSubset(currentValue, managedValue) ? JSON_REMOVE_SENTINEL : currentValue;\n  }\n\n  return currentValue === managedValue ? JSON_REMOVE_SENTINEL : currentValue;\n}\n\nfunction hydrateRecordedOperations(repoRoot, operations, trustedRoot) {\n  return operations.map(operation => {\n    if (operation.kind === 'update-claude-settings') {\n      const sourcePath = resolveOperationSourcePath(repoRoot, operation);\n      if (!sourcePath || !fs.existsSync(sourcePath)) {\n        throw new Error(\n          `Missing source file for repair: ${sourcePath || operation.sourceRelativePath}`\n        );\n      }\n      return {\n        ...operation,\n        sourcePath,\n        previousManagedHooks: operation.managedHooks,\n        managedHooks: materializeManagedHooks(\n          readHooksConfigNoFollow(sourcePath),\n          trustedRoot\n        ),\n      };\n    }\n\n    if (operation.kind !== 'copy-file') {\n      return { ...operation };\n    }\n","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/install-lifecycle.js#L716-L752","documentation":"hydrateRecordedOperations rehydrates recorded update-claude-settings operations from install-state for a repair run. It resolves the operation's source file relative to the repo root and requires that it exists, since the repair needs the canonical source content to rebuild managed settings. If resolution fails or the file is missing, it throws, naming either the resolved path or the operation's sourceRelativePath.","triggerScenarios":"Running repair (repairManagedHooks) with install-state containing an update-claude-settings operation whose sourceRelativePath no longer resolves to an existing file under repoRoot — e.g. the settings template/source file was deleted or renamed, resolveOperationSourcePath returns null, or repair is run from the wrong repo root.","commonSituations":"Repairing an install after the plugin checkout was moved, renamed, or partially deleted; a version upgrade renamed the settings source file; running repair from a different working directory than the original install repo.","solutions":["Restore the missing source file (re-clone/update the ECC repo at the same path used during install) so sourceRelativePath resolves.","Run repair from the correct repo root matching the recorded sourceRelativePath.","If the source was intentionally removed, clean the stale install-state record instead of repairing it (reinstall from scratch).","Check the error's path value and verify the file exists with that exact relative path under the repo root."],"exampleFix":"// before: sourceRelativePath 'manifests/settings.json' deleted in repo\n# after: restore the file from git\ngit checkout -- manifests/settings.json\n# then re-run repair","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst path = require('path');\nfunction assertRepairSourcesPresent(repoRoot, operations) {\n  for (const op of operations.filter(o => o.kind === 'update-claude-settings')) {\n    const p = op.sourceRelativePath && path.join(repoRoot, op.sourceRelativePath);\n    if (!p || !fs.existsSync(p)) {\n      throw new Error(`Repair source missing in repo: ${p || op.sourceRelativePath}`);\n    }\n  }\n}","typeGuard":"function repairSourceExists(repoRoot, op) {\n  const p = op.sourceRelativePath && path.join(repoRoot, op.sourceRelativePath);\n  return Boolean(p) && fs.existsSync(p);\n}","tryCatchPattern":"try {\n  await repairManagedHooks();\n} catch (err) {\n  if (/Missing source file for repair/.test(err.message)) {\n    console.error('Update/restore the ECC checkout matching the install-state, then re-run repair.');\n  } else throw err;\n}","preventionTips":["Run repair from the same repo root (and matching version) used at install time.","After upgrading ECC, prefer a fresh install over repairing stale install-state.","Keep the settings source files under version control so they can be restored."],"tags":["repair","file-not-found","state"],"backgroundTag":"file-not-found","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"}