Hmbown/CodeWhale · error · ValidationError
Cargo metadata contains duplicate workspace package names
Error message
Cargo metadata contains duplicate workspace package names
What it means
validate-crate-publish-order.py validates `cargo metadata` output before computing the crate publish order. Every workspace package in the metadata must be uniquely named; duplicates would make the name-keyed workspace_by_name map ambiguous and corrupt dependency-graph construction. It throws when the list of package names contains any repeat.
Solutions
- Run `cargo metadata --format-version 1` and grep package names for duplicates (e.g. pipe through jq '.packages[].name' | sort | uniq -d).
- Check workspace.members / workspace.exclude in the root Cargo.toml for a duplicated path.
- Rename the duplicate package in its Cargo.toml or remove the redundant member entry.
- Re-run `cargo metadata` to confirm the duplicate is gone before re-running the validator.
Example fix
// before (root Cargo.toml) members = ["crates/tui", "crates/tui"] // after members = ["crates/tui"]
Defensive patterns
Strategy: validation
Validate before calling
import json, sys
meta = json.loads(subprocess.check_output(['cargo','metadata','--format-version','1']))
names = [p['name'] for p in meta['packages']]
dups = {n for n in names if names.count(n) > 1}
if dups: sys.exit(f'duplicate workspace packages: {dups}') Try / catch
try:
validate_order(...)
except ValidationError as e:
print(f'workspace duplicate packages: {e}', file=sys.stderr); sys.exit(1) Prevention
- Keep workspace.members unique and generated where possible
- Grep new Cargo.toml package names against existing ones before committing
- Run the validator locally before pushing release changes
When it happens
Trigger: Running the validator on Cargo metadata where two workspace members resolve to the same package name — e.g. a crate listed twice in workspace.members, a vendored/duplicate package entry, or a renamed crate whose old name still exists somewhere in the graph.
Common situations: Copy-pasting a workspace member entry without removing the old one; adding a directory that contains a Cargo.toml with the same package name as an existing crate; accidental duplicate `path` dependencies pulling the same crate in twice.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Cargo metadata omits workspace package ids
- workspace packages have mixed versions
- Cargo metadata dependencies for
- cargo metadata failed with exit code
- Cargo metadata must contain workspace_members and packages…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/a64b7796390e437c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/release/validate-crate-publish-order.py:96
return [packages_by_id[member] for member in members]
def validate_order(
packages: list[dict[str, Any]], ordered_crates: list[str]
) -> tuple[str, dict[str, bool]]:
duplicate_crates = sorted(
{name for name in ordered_crates if ordered_crates.count(name) > 1}
)
if duplicate_crates:
raise ValidationError(
"publish package list contains duplicates: " + ", ".join(duplicate_crates)
)
names = [package.get("name") for package in packages]
if any(not isinstance(name, str) or not name for name in names):
raise ValidationError("workspace package is missing a name")
if len(set(names)) != len(names):
raise ValidationError("Cargo metadata contains duplicate workspace package names")
versions = sorted({package.get("version") for package in packages})
if len(versions) != 1 or not isinstance(versions[0], str) or not versions[0]:
rendered = ", ".join(str(version) for version in versions)
raise ValidationError(f"workspace packages have mixed versions: {rendered}")
workspace_by_name = {package["name"]: package for package in packages}
release_names = sorted(
name for name in workspace_by_name if name.startswith("codewhale-")
)
ordered_set = set(ordered_crates)
missing = sorted(set(release_names) - ordered_set)
extra = sorted(ordered_set - set(release_names))
if missing or extra:
messages = []
if missing:
messages.append("publish package list is missing workspace crates: " + " ".join(missing))
if extra:View on GitHub (pinned to 433685b202)