abhigyanpatwari/GitNexus · warning
[python-workspace-extractor] duplicate package "${manifest.n
Error message
[python-workspace-extractor] duplicate package "${manifest.name}" in "${groupPath}" and "${existing.groupPath}" — skipping "${groupPath}" What it means
Emitted by the group Python workspace extractor. Two scanned directories produced manifests whose import name (importName) is identical; packages are keyed by importName in a packagesByImportName map, so the later registration (groupPath) is skipped and its workspace dependency links are never built. Cross-repo resolution for the skipped package degrades after this warning.
Source
Thrown at gitnexus/src/core/group/extractors/python-workspace-extractor.ts:214
const packagesByGroupPath = new Map<string, PythonPackageMeta>();
for (const [groupPath] of Object.entries(repos)) {
const repoPath = repoPaths.get(groupPath);
if (!repoPath) continue;
const manifest = await parsePythonManifest(repoPath);
if (!manifest) continue;
const meta: PythonPackageMeta = {
name: manifest.name,
importName: manifest.importName,
groupPath,
repoPath,
workspaceDeps: manifest.deps,
};
const existing = packagesByImportName.get(manifest.importName);
if (existing) {
logger.warn(
`[python-workspace-extractor] duplicate package "${manifest.name}" in "${groupPath}" and "${existing.groupPath}" — skipping "${groupPath}"`,
);
continue;
}
packagesByImportName.set(manifest.importName, meta);
packagesByGroupPath.set(groupPath, meta);
}
const links: GroupManifestLink[] = [];
const seen = new Set<string>();
for (const [, pkg] of packagesByGroupPath) {
const normalizedDeps = pkg.workspaceDeps.map((d) => d.replace(/-/g, '_'));
const groupPkgDeps = normalizedDeps.filter((d) => packagesByImportName.has(d));
if (groupPkgDeps.length === 0) continue;
const knownPackages = new Map<string, string>();
for (const dep of groupPkgDeps) {View on GitHub (pinned to 52924ef12c)
Solutions
- Rename the duplicate package's project name and top-level import package so importName is unique
- Ignore or remove the vendored duplicate so the extractor does not scan it
- Re-run group analyze and verify the warning disappears and workspace links resolve
Example fix
# before — repo-b/pyproject.toml [project] name = "payments-lib" # after [project] name = "payments-lib-v2" # rename the import package dir to match
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
function assertUniquePythonImports(repoDirs: string[]): void {
const seen = new Map<string, string>();
for (const dir of repoDirs) {
let name: string | undefined;
try {
const raw = JSON.parse(readFileSync(join(dir, 'pyproject.json-dump'), 'utf8')); // or parse TOML
name = raw?.project?.name ?? raw?.tool?.poetry?.name;
} catch {
continue;
}
if (!name) continue;
const importName = name.replaceAll('-', '_').replaceAll('.', '_');
if (seen.has(importName)) {
throw new Error(`duplicate import "${importName}" in ${seen.get(importName)} and ${dir}`);
}
seen.set(importName, dir);
}
} Type guard
function hasUniqueImports<T extends { importName: string }>(items: readonly T[]): boolean {
return new Set(items.map((i) => i.importName)).size === items.length;
} Prevention
- Give every Python package in a group a unique project name and top-level module directory
- Do not vendor a package copy into a sibling group repo; reference it via the group link manifest instead
- Fail CI on duplicate project names across group repos before running group sync
When it happens
Trigger: A group contains two pyproject.toml/setup.py declaring the same project or import name — a library vendored into a second repo, or two packages whose top-level module directory resolves to the same import name.
Common situations: Forked Python packages kept in one group; duplicated internal utility libraries; src-layout packages that both expose the same top-level module name.
Related errors
- [node-workspace-extractor] duplicate package name "${manifes
- [rust-workspace-extractor] duplicate crate name "${manifest.
- [node] package.json scan of ${repoRoot} hit the ${SCAN_MAX_D
- [cfg] Python buildFunctionCfg skipped a function in ${filePa
AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-08-20).
Data as JSON: /api/errors/6a6bcb0a11463052.
Report an issue: GitHub.