abhigyanpatwari/GitNexus · error · RegistryNameCollisionError
Registry name "${registryName}" is already used by "${existi
Error message
Registry name "${registryName}" is already used by "${existingPath}".
Pass --name <alias> to register "${requestedPath}" under a different name, or --allow-duplicate-name to allow both paths under the same name (leaves -r <name> ambiguous for these two). What it means
The global registry (~/.gitnexus/registry.json) keys repos by name. When you register with an explicit --name (or a preserved alias) that is already taken by a different canonical path (canonical-vs-canonical comparison, so /var/foo vs /private/var/foo does NOT collide), registration refuses rather than silently shadowing the existing entry, and points at the two escape hatches: --name <alias> or --allow-duplicate-name.
Source
Thrown at gitnexus/src/storage/repo-manager.ts:851
// Duplicate-name guard: only fire when the user EXPLICITLY asked for
// this name (via opts.name or a preserved alias). Unqualified basename
// and remote-inferred collisions are preserved for backward-compat —
// they still register, and the user sees the ambiguity at `-r` / `list`
// resolution time (which is already improved by the disambiguated error
// messages and list output #829 ships).
const explicitName = opts?.name !== undefined || isPreservedAlias;
if (explicitName && !opts?.allowDuplicateName) {
// Compare canonical-vs-canonical here too so `/var/foo` and
// `/private/var/foo` (same repo, different form) aren't treated as
// two colliding paths.
const collidingEntry = entries.find(
(e, i) =>
i !== existingIdx &&
e.name.toLowerCase() === name.toLowerCase() &&
canonicalizePath(e.path) !== canonicalInput,
);
if (collidingEntry) {
throw new RegistryNameCollisionError(name, collidingEntry.path, resolved);
}
}
// This run's branch summary (non-primary runs only); hoisted so the
// re-read-before-write merge below can re-apply it against a fresh snapshot.
const summary: BranchSummary | null = opts?.branch
? {
branch: opts.branch,
indexedAt: meta.indexedAt,
lastCommit: meta.lastCommit,
stats: meta.stats,
}
: null;
let entry: RegistryEntry;
if (summary) {
// Non-primary branch run (#2106): keep the primary's top-level fields and
// upsert this branch into branches[]. One entry per path is preserved.View on GitHub (pinned to aac7515d2a)
Solutions
- Register under a distinct alias: gitnexus analyze --name app-ci /repoB
- If both should share the name (accepting that -r app becomes ambiguous), pass --allow-duplicate-name
- Remove the stale entry first: gitnexus remove /repoA, then re-run analyze
- List current registrations first so you can see the collision before choosing
Example fix
# before gitnexus analyze --name app /repoB # → RegistryNameCollisionError # after gitnexus analyze --name app-ci /repoB # or intentionally keep both under 'app': gitnexus analyze --name app --allow-duplicate-name /repoB
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
function nameTakenByOtherPath(name: string, myPath: string): string | null {
const registry = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.gitnexus', 'registry.json'), 'utf8'));
const hit = (registry.repos ?? []).find(
(e: { name: string; path: string }) =>
e.name.toLowerCase() === name.toLowerCase() &&
path.resolve(e.path) !== path.resolve(myPath),
);
return hit?.path ?? null;
}
if (nameTakenByOtherPath('app', process.cwd())) registryName = 'app-2'; Prevention
- Check the registry for name collisions before registering a second same-named clone
- Give CI and fork checkouts distinct --name aliases up front
- Use --allow-duplicate-name only when you accept that -r <name> becomes ambiguous
When it happens
Trigger: `gitnexus analyze --name app` run in /repoB when 'app' is already registered for the different path /repoA — names match case-insensitively, canonical paths differ.
Common situations: Two clones or forks with the same folder name indexed from different directories (work machine vs CI, upstream vs fork); moving a repo and re-registering under its previous name; teams sharing a machine with same-named checkouts.
Related errors
- Analysis did not finalize for ${repoPath}: registry entry fo
- Refusing to remove storage path for safety: expected "${expe
- Multiple registered repos match "${target}": ${listing} Pass
- No registered repo matches "${target}".${hint}
- ${source}: branch name must not contain a backtick (it would
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/603acc6c349bbf94.
Report an issue: GitHub.