abhigyanpatwari/GitNexus · error
Duplicate auto-sync targetDir ${targetDir} for ${previous} a
Error message
Duplicate auto-sync targetDir ${targetDir} for ${previous} and ${remoteUrl} What it means
buildWorkItems derives a targetDir for each remote URL of a project and enforces that each target directory is owned by exactly one remote URL. If two remote URLs resolve to the same local clone path, the run would race or clobber files, so it throws instead of proceeding.
Source
Thrown at gitnexus/src/core/auto-sync/runner.ts:461
const items: AutoSyncWorkItem[] = [];
const targetOwners = new Map<string, string>();
for (const project of config.projects) {
let cloneRoot: AutoSyncWorkItem['cloneRoot'];
try {
cloneRoot = await deps.resolveCloneRoot(project.localPath);
} catch (err: unknown) {
for (const remoteUrl of project.remoteUrls) {
items.push({ project, remoteUrl, error: shortErrorMessage(err) });
}
continue;
}
for (const remoteUrl of project.remoteUrls) {
try {
const repoName = extractRepoNameFromRemoteUrl(remoteUrl);
const targetDir = getConfiguredRepoPath({ localPath: cloneRoot.root }, repoName, remoteUrl);
const previous = targetOwners.get(targetDir);
if (previous !== undefined) {
throw new Error(
`Duplicate auto-sync targetDir ${targetDir} for ${previous} and ${remoteUrl}`,
);
}
targetOwners.set(targetDir, remoteUrl);
items.push({ project, remoteUrl, cloneRoot, repoName, targetDir });
} catch (err: unknown) {
items.push({ project, remoteUrl, error: shortErrorMessage(err) });
}
}
}
return items;
}
async function mapWithConcurrency<T, R>(
items: T[],
concurrency: number,
signal: AbortSignal | undefined,
worker: (item: T) => Promise<R>,View on GitHub (pinned to 0d1aed942f)
Solutions
- Remove the duplicate remote URL from the project's remoteUrls config so each URL maps to a unique targetDir.
- Configure a distinct clone root or repo path override (getConfiguredRepoPath) so colliding repos get separate directories.
- Normalize your remote URLs to one scheme (all https or all ssh) to avoid scheme-based name collisions.
- Rename one of the repos if two repo names resolve to the same directory name.
Example fix
// before (project config) "remoteUrls": ["https://github.com/acme/api.git", "git@github.com:acme/api.git"] // after "remoteUrls": ["https://github.com/acme/api.git"]
Defensive patterns
Strategy: validation
Validate before calling
const dirs = project.remoteUrls.map((u) =>
getConfiguredRepoPath({ localPath: cloneRoot.root }, extractRepoNameFromRemoteUrl(u), u),
);
if (new Set(dirs).size !== dirs.length) {
throw new Error('remoteUrls resolve to duplicate target directories');
} Try / catch
try {
items = await workItems();
} catch (err) {
if (String(err.message).startsWith('Duplicate auto-sync targetDir')) {
logger.error('fix project remoteUrls:', err.message);
return;
}
throw err;
} Prevention
- Keep one canonical remote URL per project (https form).
- Deduplicate remoteUrls in config parsing.
- Ensure repo names uniquely map to directory names in the clone root.
When it happens
Trigger: Calling buildWorkItems (via workItems) for a project whose remoteUrls list contains two URLs (e.g. https and ssh forms, or duplicates) that extractRepoNameFromRemoteUrl + getConfiguredRepoPath collapse into the same targetDir.
Common situations: A project configured with both an HTTPS and an SSH remote for the same repo; a copy-pasted duplicate remote URL; two distinct repos whose names normalize to the same directory in the clone root.
Related errors
- must not contain backticks
- must not end with "/" or "."
- must not contain consecutive slashes
- must not contain "@{"
- must not contain hidden, trailing-dot, or .lock path compone
AI-assisted analysis of abhigyanpatwari/GitNexus@0d1aed942f (2026-09-08).
Data as JSON: /api/errors/6e8b88bef2d0c9c6.
Report an issue: GitHub.