ruvnet/ruflo · error · Error
repository changed while hashing untracked entry: ${path}
Error message
repository changed while hashing untracked entry: ${path} What it means
untrackedManifest() lstat's each untracked entry before and after reading its content and compares mode, size, mtimeMs, and ino. Any difference means the file changed between the two stats (a TOCTOU window), so the capture refuses to record a torn state instead of hashing a half-written file.
Source
Thrown at v3/@claude-flow/codex/src/harness/repository-state.ts:274
let kind: UntrackedFileIdentity['kind'];
let content: Buffer;
if (before.isSymbolicLink()) {
kind = 'symlink';
content = Buffer.from(readlinkSync(absolute), 'utf8');
} else if (before.isFile()) {
kind = 'file';
content = readFileSync(absolute);
} else {
throw new Error(`unsupported untracked repository entry: ${path}`);
}
const after = lstatSync(absolute);
if (
before.mode !== after.mode
|| before.size !== after.size
|| before.mtimeMs !== after.mtimeMs
|| before.ino !== after.ino
) {
throw new Error(`repository changed while hashing untracked entry: ${path}`);
}
return {
path,
kind,
mode: before.mode & 0o7777,
bytes: content.byteLength,
digest: digest(content),
};
});
return { digest: digest(canonicalJson(entries)), entries };
}
function trackedPatch(repoRoot: string): ContentDigest {
return contentDigest(gitBuffer(repoRoot, [
'diff',
'--binary',
'--full-index',
'--no-ext-diff',View on GitHub (pinned to fa13ee4ad6)
Solutions
- Stop the concurrent writer (watchers, builds, other agent sessions) and re-run the capture
- Commit or stash work so the tree is quiescent before capturing
- Retry the capture — transient writes usually clear on the second attempt
Defensive patterns
Strategy: retry
Validate before calling
function isQuiescent(abs: string): boolean {
const a = lstatSync(abs);
const content = readFileSync(abs);
const b = lstatSync(abs);
return a.mtimeMs === b.mtimeMs && a.size === b.size && a.ino === b.ino;
} Try / catch
for (let attempt = 1; attempt <= 3; attempt++) {
try { return capture(); }
catch (e) { if (!/changed while hashing/.test(String(e))) throw e; }
} Prevention
- Stop watchers, builds, and other agent sessions before capturing
- Prefer clean checkouts for snapshotting instead of live workspaces
- Stash or commit dirty state so the clean fast path applies
When it happens
Trigger: Any process writes to an untracked file during capture: build output, `npm install`, formatters, watch mode, another agent or editor saving the file mid-read.
Common situations: Running capture while `npm run build`, a bundler --watch, or another AI agent is actively writing to the worktree; CI pipelines that generate artifacts during the same phase as the snapshot.
Related errors
- unsupported untracked repository entry: ${path}
- repository changed while capturing exact source state
- build evidence path is not a file or symlink: ${path}
- Git-visible source state does not match the build evidence r
- Git-visible source state changed before build evidence recom
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/66e33c3ec6b52a48.
Report an issue: GitHub.