affaan-m/ECC · error
Missing source file for repair
Error message
Missing source file for repair: ${sourcePath || operation.sourceRelativePath} What it means
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.
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.
Example fix
// before: sourceRelativePath 'manifests/settings.json' deleted in repo # after: restore the file from git git checkout -- manifests/settings.json # then re-run repair
Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
const path = require('path');
function assertRepairSourcesPresent(repoRoot, operations) {
for (const op of operations.filter(o => o.kind === 'update-claude-settings')) {
const p = op.sourceRelativePath && path.join(repoRoot, op.sourceRelativePath);
if (!p || !fs.existsSync(p)) {
throw new Error(`Repair source missing in repo: ${p || op.sourceRelativePath}`);
}
}
} Type guard
function repairSourceExists(repoRoot, op) {
const p = op.sourceRelativePath && path.join(repoRoot, op.sourceRelativePath);
return Boolean(p) && fs.existsSync(p);
} Try / catch
try {
await repairManagedHooks();
} catch (err) {
if (/Missing source file for repair/.test(err.message)) {
console.error('Update/restore the ECC checkout matching the install-state, then re-run repair.');
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- a top-level committed transaction is required
- Agents directory not found
- asset must be a local regular file
- cannot open
- cannot open video
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/5ce4edb967a772f4.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/install-lifecycle.js:734
}
}
return Object.keys(nextValue).length === 0 ? JSON_REMOVE_SENTINEL : nextValue;
}
if (Array.isArray(managedValue)) {
return jsonContainsSubset(currentValue, managedValue) ? JSON_REMOVE_SENTINEL : currentValue;
}
return currentValue === managedValue ? JSON_REMOVE_SENTINEL : currentValue;
}
function hydrateRecordedOperations(repoRoot, operations, trustedRoot) {
return operations.map(operation => {
if (operation.kind === 'update-claude-settings') {
const sourcePath = resolveOperationSourcePath(repoRoot, operation);
if (!sourcePath || !fs.existsSync(sourcePath)) {
throw new Error(
`Missing source file for repair: ${sourcePath || operation.sourceRelativePath}`
);
}
return {
...operation,
sourcePath,
previousManagedHooks: operation.managedHooks,
managedHooks: materializeManagedHooks(
readHooksConfigNoFollow(sourcePath),
trustedRoot
),
};
}
if (operation.kind !== 'copy-file') {
return { ...operation };
}
View on GitHub (pinned to 8321021c54)