abhigyanpatwari/GitNexus · warning

[node-workspace-extractor] duplicate package name "${manifes

Error message

[node-workspace-extractor] duplicate package name "${manifest.name}" in "${groupPath}" and "${existing.groupPath}" — skipping "${groupPath}"

What it means

Emitted by the group Node workspace extractor while registering workspace packages across a group's repos. Two scanned directories produced package.json manifests with the identical "name" field; since packages are keyed by name in a packagesByName map, the later registration (groupPath) is dropped and only the first wins. The skipped package contributes no workspace dependency links, so cross-repo resolution for it silently degrades after this warning.

Source

Thrown at gitnexus/src/core/group/extractors/node-workspace-extractor.ts:209

  const packagesByName = new Map<string, PackageMeta>();
  const packagesByGroupPath = new Map<string, PackageMeta>();

  for (const [groupPath] of Object.entries(repos)) {
    const repoPath = repoPaths.get(groupPath);
    if (!repoPath) continue;

    const manifest = await parsePackageManifest(repoPath);
    if (!manifest) continue;

    const meta: PackageMeta = {
      name: manifest.name,
      groupPath,
      repoPath,
      workspaceDeps: manifest.workspaceDeps,
    };
    const existing = packagesByName.get(manifest.name);
    if (existing) {
      logger.warn(
        `[node-workspace-extractor] duplicate package name "${manifest.name}" in "${groupPath}" and "${existing.groupPath}" — skipping "${groupPath}"`,
      );
      continue;
    }
    packagesByName.set(manifest.name, meta);
    packagesByGroupPath.set(groupPath, meta);
  }

  const links: GroupManifestLink[] = [];
  const seen = new Set<string>();

  for (const [, pkg] of packagesByGroupPath) {
    const groupPkgDeps = pkg.workspaceDeps.filter((d) => packagesByName.has(d));
    if (groupPkgDeps.length === 0) continue;

    const knownPackages = new Set(groupPkgDeps);
    const imports = await scanImports(pkg.repoPath, knownPackages);

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Rename the duplicate package.json "name" to a unique value (e.g. scope it: "@org/api-lib") so both packages register
  2. If one copy is vendored or generated, add it to the repo's ignore rules so the extractor never scans it
  3. Remove or merge the stale fork carrying the duplicate name
  4. Re-run group analyze and confirm the warning is gone and workspace links resolve

Example fix

// before — packages/a/package.json
{ "name": "api-lib", "version": "1.0.0" }
// packages/b/package.json
{ "name": "api-lib", "version": "2.0.0" }

// after — packages/b/package.json
{ "name": "@org/api-lib-v2", "version": "2.0.0" }
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from 'node:fs';
import { join } from 'node:path';

function assertUniquePackageNames(repoDirs: string[]): void {
  const seen = new Map<string, string>();
  for (const dir of repoDirs) {
    let name: string | undefined;
    try {
      name = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).name;
    } catch {
      continue; // no manifest — the extractor skips it too
    }
    if (!name) continue;
    if (seen.has(name)) {
      throw new Error(`duplicate package name "${name}" in ${seen.get(name)} and ${dir}`);
    }
    seen.set(name, dir);
  }
}
// run before group sync
assertUniquePackageNames(groupRepoDirs);

Type guard

function hasUniqueNames<T extends { name: string }>(items: readonly T[]): boolean {
  return new Set(items.map((i) => i.name)).size === items.length;
}

Prevention

When it happens

Trigger: Running group analyze/sync on a group where two workspace members (or two group repos) both declare e.g. "name": "api-lib" in package.json: a vendored copy of a package, a fork that kept the original name, or a template package instantiated twice.

Common situations: Monorepos with vendored or example packages duplicating a real package's name; groups containing both a library and its vendored copy; renamed packages where one directory still carries the old package.json name.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/9a16f8589f28e795. Report an issue: GitHub.