abhigyanpatwari/GitNexus · warning

[rust-workspace-extractor] duplicate crate name "${manifest.

Error message

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

What it means

Emitted by the group Rust workspace extractor. Two scanned directories produced Cargo.toml manifests with the same crate "name"; crates are keyed by name in a cratesByName map, so the later registration (groupPath) is skipped and Phase 2 linking never runs for it. Workspace dependency links for the skipped crate are silently absent after this warning.

Source

Thrown at gitnexus/src/core/group/extractors/rust-workspace-extractor.ts:251

  const cratesByName = new Map<string, CrateMeta>();
  const cratesByGroupPath = new Map<string, CrateMeta>();

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

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

    const meta: CrateMeta = {
      name: manifest.name,
      groupPath,
      repoPath,
      workspaceDeps: manifest.workspaceDeps,
    };
    const existing = cratesByName.get(manifest.name);
    if (existing) {
      logger.warn(
        `[rust-workspace-extractor] duplicate crate name "${manifest.name}" in "${groupPath}" and "${existing.groupPath}" — skipping "${groupPath}"`,
      );
      continue;
    }
    cratesByName.set(manifest.name, meta);
    cratesByGroupPath.set(groupPath, meta);
  }

  // Phase 2: For each crate, identify which of its workspace deps are
  // also in this group (i.e., repos we can link to)
  const links: GroupManifestLink[] = [];
  const seen = new Set<string>();

  for (const [, crate] of cratesByGroupPath) {
    const groupCrateDeps = crate.workspaceDeps.filter((d) => cratesByName.has(d));
    if (groupCrateDeps.length === 0) continue;

    // Phase 3: Scan source files for imports from workspace deps

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Rename the duplicate crate's name in Cargo.toml (and any path dependencies referencing it)
  2. If one copy is vendored or generated, add it to ignore rules so the extractor skips it
  3. Remove or merge the stale duplicate
  4. Re-run group analyze and confirm the warning is gone and crate links resolve

Example fix

# before — crates/b/Cargo.toml
[package]
name = "common-utils"
version = "0.2.0"

# after
[package]
name = "common-utils-v2"
version = "0.2.0"
Defensive patterns

Strategy: validation

Validate before calling

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

function assertUniqueCrateNames(repoDirs: string[]): void {
  const seen = new Map<string, string>();
  for (const dir of repoDirs) {
    let name: string | undefined;
    try {
      const toml = readFileSync(join(dir, 'Cargo.toml'), 'utf8');
      name = /^name\s*=\s*"([^"]+)"/m.exec(toml)?.[1];
    } catch {
      continue;
    }
    if (!name) continue;
    if (seen.has(name)) {
      throw new Error(`duplicate crate name "${name}" in ${seen.get(name)} and ${dir}`);
    }
    seen.set(name, dir);
  }
}

Type guard

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

Prevention

When it happens

Trigger: A group contains two workspace members (or two group repos) whose Cargo.toml both declare e.g. name = "common-utils": a vendored crate copy, a fork that kept the original crate name, or a template member instantiated twice.

Common situations: Vendored crates duplicated inside a group repo; forked crates that kept the upstream name; example workspace members copying a real crate's name.

Related errors


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