santifer/career-ops · critical
Validation failed ( ) and revert also failed ( )
Error message
Validation failed (${err.message}) and revert also failed (${revertErr.message}) What it means
After applying updates, update-system.mjs validates the result (e.g. via git status). If validation fails it tries to revert the touched paths with revertPaths(); if that revert also fails, it throws this combined error chaining the original validation failure via `cause` so neither diagnostic is lost. It signals the worktree is in an unknown, partially-reverted state needing manual attention.
Solutions
- Read err.cause (`cause`) to see the original validation error and fix that root problem.
- Remove a stale lock file if present: check for .git/index.lock and delete it if no git process is running.
- Manually revert the updated files: `git checkout -- <paths>` or `git restore <paths>`.
- Re-run `node update-system.mjs apply --confirm` after the repo is healthy.
Example fix
# before (broken state) rm -f .git/index.lock git restore modes/ scripts/ # or: git checkout -- . # after node update-system.mjs apply --confirm
Defensive patterns
Strategy: try-catch
Validate before calling
// before applying, ensure the repo is healthy:
execFileSync('git', ['status', '--porcelain'], { cwd: ROOT });
execFileSync('git', ['diff', '--quiet']); Try / catch
try {
applyUpdate();
} catch (e) {
if (e.message.startsWith('Validation failed') && e.cause) {
console.error('root cause:', e.cause.message);
console.error('revert manually: git restore .');
} else throw e;
} Prevention
- Clear stale .git/index.lock before running updates.
- Run the updater when no other git process is active.
- Keep sufficient disk space and writable repo permissions.
- Commit or stash local changes before applying updates.
When it happens
Trigger: Post-apply validation threw (err), revertPaths(updated, initialStatusPaths) also threw (revertErr) — typically because whatever broke `git status` (index lock, corrupt index) also breaks `git checkout --`.
Common situations: A stale .git/index.lock left by another git process; concurrent git operations during the update; disk-full or permission problems in the repo; an editor or watcher holding files during apply.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- Safety violation ( ) and revert also failed ( )
- a 40-hex commit --sha is required
- addPaths received directory pathspec(s), which -f would…
- Cannot verify tracker lock ownership at
- career-ops at is not a git checkout of its own, so git…
AI-assisted analysis of santifer/career-ops@e7abd431fc (2026-09-16).
Data as JSON: /api/errors/3bc4152e4c451063.
Report an issue: GitHub.
Appendix: source
Thrown at update-system.mjs:2427
const changed = gitStatusEntries()
.map((entry) => entry.path)
.filter((file) => !initialStatusPaths.has(file) && !generatedBackupPaths.has(file));
for (const file of userLayerViolations(changed, updatePaths, effectiveUserPaths())) {
console.error(`SAFETY VIOLATION: User file was modified: ${file}`);
violatedUserPaths.add(file);
}
} catch (err) {
// Fail closed: if we can't validate the safety invariant we must
// not silently proceed — that would let a real violation slip
// through. Revert what we already applied and abort.
console.error(`Aborting: could not validate user-layer safety (${err.message}).`);
try {
revertPaths(updated, initialStatusPaths);
} catch (revertErr) {
// If the revert itself fails (likely whatever broke `git
// status` also broke `git checkout --`), don't lose the
// original validation error — chain it via `cause`.
throw new Error(
`Validation failed (${err.message}) and revert also failed (${revertErr.message})`,
{ cause: err },
);
}
throw err;
}
if (violatedUserPaths.size > 0) {
console.error('Aborting: user files were touched. Rolling back system files...');
// Revert ONLY the system-layer updates — never `git checkout` the
// violated user paths back to HEAD. Doing so would overwrite the
// user's working-tree content (accumulated STAR+R stories, local
// edits) with whatever is committed upstream, causing data loss.
// The user files were flagged as touched by the update, not by the
// user; leaving them as-is is the safe choice — the user decides
// what to do with them.
const violation = new Error('Update aborted: user files were touched.');
try {View on GitHub (pinned to e7abd431fc)