Hmbown/CodeWhale · error · ValidationError
workspace packages have mixed versions: {rendered}
Error message
workspace packages have mixed versions: {rendered} What it means
The set of workspace package versions does not reduce to exactly one non-empty string -- the crates are not all on the same version. The release process publishes every codewhale-* crate in lockstep and the validator returns the single discovered version to the publish script, so mixed versions (or a missing/non-string version) abort validation with the versions rendered in the message.
Source
Thrown at scripts/release/validate-crate-publish-order.py:101
) -> 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:
messages.append(
"publish package list contains non-workspace crates: " + " ".join(extra)
)
raise ValidationError("\n".join(messages))
View on GitHub (pinned to 8880682c63)
Solutions
- Set the straggler crate to inherit the workspace version: in its Cargo.toml use version.workspace = true under [package]
- Ensure [workspace.package] declares the shared version
- Re-run the validator; cargo metadata --locked --format-version 1 --no-deps | jq -r '.packages[].version' | sort -u should print exactly one version
Example fix
# crates/<straggler>/Cargo.toml: before [package] name = "codewhale-x" version = "0.4.0" # after [package] name = "codewhale-x" version.workspace = true
Defensive patterns
Strategy: validation
Validate before calling
# Pre-release check: exactly one version across the workspace
import json, subprocess
meta = json.loads(subprocess.run(
["cargo", "metadata", "--locked", "--format-version", "1", "--no-deps"],
capture_output=True, text=True, check=True).stdout)
versions = {p["version"] for p in meta["packages"] if p["id"] in set(meta["workspace_members"])}
assert len(versions) == 1, f"align versions before release: {sorted(versions)}" Prevention
- Use version.workspace = true in every member so the workspace version is the single knob
- Run the version check as part of the release checklist before tagging
When it happens
Trigger: One crate's Cargo.toml carries a hardcoded version while the rest use the workspace version; a release bump script updated most crates but missed one; a newly added crate was created with a different initial version.
Common situations: Release preparation where the version-anchoring convention (workspace-inherited version) is not followed by every member.
Related errors
- Cargo metadata contains duplicate workspace package names
- publish package list is missing workspace crates: {missing}
- could not read Cargo metadata: {error}
- cargo metadata failed with exit code {process.returncode}{su
- Cargo metadata is not valid JSON: {error}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/b9d9a383d97a5fcf.
Report an issue: GitHub.