ruvnet/ruflo · error · Error
unsupported untracked repository entry: ${path}
Error message
unsupported untracked repository entry: ${path} What it means
While building the untracked manifest, each entry is lstat'ed and only two kinds are accepted: regular files and symlinks. Anything else — FIFO, unix socket, device node, or a directory appearing in the list — throws 'unsupported untracked repository entry'.
Source
Thrown at v3/@claude-flow/codex/src/harness/repository-state.ts:265
function untrackedManifest(repoRoot: string): UntrackedManifest {
const output = gitBuffer(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z']);
const paths = splitNul(output).map(decodeGitPath).sort(codeUnitCompare);
assertNoPathCollisions(paths);
const entries = paths.map((path): UntrackedFileIdentity => {
const absolute = resolve(repoRoot, path);
assertInsideRepository(repoRoot, absolute);
const before = lstatSync(absolute);
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),
};
});View on GitHub (pinned to fa13ee4ad6)
Solutions
- Locate the entry named in the message and run `ls -la` on it to confirm its type
- Delete the special file or move it outside the worktree
- Add its directory/pattern to .gitignore so --exclude-standard skips it
Example fix
# find and remove untracked special files find . -path ./.git -prune -o ! -type d ! -type f ! -type l -print rm .claude-flow/dev.sock # or ignore the directory echo '.claude-flow/' >> .gitignore
Defensive patterns
Strategy: validation
Validate before calling
import { lstatSync } from 'node:fs';
function isSupportedEntry(abs: string): boolean {
const s = lstatSync(abs);
return s.isFile() || s.isSymbolicLink();
} Try / catch
try { capture(); } catch (e) { if (/unsupported untracked repository entry/.test(String(e))) { cleanSpecialFiles(); retryCapture(); } throw e; } Prevention
- Keep runtime scratch (sockets, FIFOs, pidfiles) in gitignored directories
- Add dev-server socket paths to .gitignore
- Sweep for special files before capture: find . ! -type d ! -type f ! -type l
When it happens
Trigger: An untracked named pipe (`mkfifo .claude-flow/pipe`), a socket file left by a dev server, or a device node exists inside the worktree and is not gitignored, so `git ls-files --others --exclude-standard` returns it.
Common situations: Local tooling (editors, language servers, dev servers) leaves sockets/FIFOs in the project tree; containerized dev environments mount device nodes into the worktree; the .gitignore does not cover the runtime scratch directory.
Related errors
- repository changed while hashing untracked entry: ${path}
- 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
- Git returned a non-NUL-terminated path list
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/601526dd08cf88aa.
Report an issue: GitHub.