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

  1. Set the straggler crate to inherit the workspace version: in its Cargo.toml use version.workspace = true under [package]
  2. Ensure [workspace.package] declares the shared version
  3. 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

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


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/b9d9a383d97a5fcf. Report an issue: GitHub.