ruvnet/ruflo · error · Error
duplicate repository path: ${path}
Error message
duplicate repository path: ${path} What it means
assertNoPathCollisions() builds the sorted list of tracked plus untracked paths from `git ls-files` and refuses the capture when the exact same path string appears twice. Git's index should never emit a duplicate, so this error almost always indicates a corrupted index or a modified/wrapped git that returns repeated entries.
Source
Thrown at v3/@claude-flow/codex/src/harness/repository-state.ts:216
assertUnicodeScalarString(path);
if (path.includes('\\')) throw new Error(`ambiguous repository path separator: ${path}`);
const normalized = path.normalize('NFC');
if (
normalized.length === 0
|| isAbsolute(normalized)
|| normalized.startsWith('-')
|| normalized.split('/').some((part) => part === '' || part === '.' || part === '..')
) {
throw new Error(`unsafe repository-relative path: ${path}`);
}
return normalized;
}
function assertNoPathCollisions(paths: readonly string[]): void {
const exact = new Set<string>();
const folded = new Map<string, string>();
for (const path of paths) {
if (exact.has(path)) throw new Error(`duplicate repository path: ${path}`);
exact.add(path);
const key = portableCaseFold(path);
const prior = folded.get(key);
if (prior !== undefined && prior !== path) {
throw new Error(`case-fold repository path collision: ${prior} and ${path}`);
}
folded.set(key, path);
}
}
function repositoryPaths(repoRoot: string, includeUntracked: boolean): readonly string[] {
const tracked = splitNul(gitBuffer(repoRoot, ['ls-files', '-z'])).map(decodeGitPath);
const untracked = includeUntracked
? splitNul(gitBuffer(repoRoot, ['ls-files', '--others', '--exclude-standard', '-z'])).map(decodeGitPath)
: [];
const paths = [...tracked, ...untracked].sort(codeUnitCompare);
assertNoPathCollisions(paths);
return paths;View on GitHub (pinned to fa13ee4ad6)
Solutions
- Run `git ls-files | sort | uniq -d` to identify the duplicated path
- Rebuild the index: `rm .git/index && git reset` (or `git read-tree HEAD`)
- Re-clone the repository if the index keeps corrupting, and remove any git output wrappers/aliases
Defensive patterns
Strategy: validation
Validate before calling
const dupes = paths.filter((p, i) => paths.indexOf(p) !== i);
if (dupes.length) throw new Error(`duplicate paths: ${dupes.join(', ')}`); Try / catch
try { capture(); } catch (e) { if (/duplicate repository path/.test(String(e))) { rebuildIndex(); } throw e; } Prevention
- Never build path lists by concatenating outputs of multiple git commands without deduping
- Use new Set(paths) before passing collections to harness code
- Rebuild the index after git crashes to prevent duplicate entries
When it happens
Trigger: `git ls-files -z` (or `--others`) emitting the same entry twice: broken .git/index after a crash, third-party git wrappers that concatenate outputs, or manually constructed path lists passed with the same entry twice.
Common situations: A crashed git process left a duplicated index entry; a git alias/wrapper merges results of multiple invocations; case-insensitive filesystems (macOS/Windows) surfaced two index rows that decode to the identical string.
Related errors
- duplicate declared build input
- duplicate declared toolchain
- malformed Git index record
- repoPath must be the Git top-level: ${top}
- repoRoot must be the git top-level: ${top}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/01c0e767b547c8b5.
Report an issue: GitHub.