Hmbown/CodeWhale · error · ValidationError

publish package list is missing workspace crates

Error message

publish package list is missing workspace crates: {missing} / publish package list contains non-workspace crates: {extra}

What it means

The validator compares the crates listed in scripts/release/crates.sh (ordered_crates, the publish order) against the codewhale-* crates found in cargo metadata. If the two sets differ in either direction — a workspace release crate missing from the publish list, or a listed crate that is not in the workspace — it raises a combined error listing the missing and extra names.

Solutions

  1. Read the `missing`/`extra` names in the error message.
  2. Add each missing workspace crate to scripts/release/crates.sh in correct dependency order.
  3. Remove or correct each extra entry that is not a workspace crate.
  4. Re-run the validator; if order errors appear next, fix positions before re-checking.

Example fix

// before (scripts/release/crates.sh)
CRATES=(codewhale-config codewhale-protocol)
// after
CRATES=(codewhale-config codewhale-protocol codewhale-tui)
Defensive patterns

Strategy: validation

Validate before calling

import subprocess, json
meta = json.loads(subprocess.check_output(['cargo','metadata','--format-version','1']))
ws = {p['name'] for p in meta['packages'] if p['name'].startswith('codewhale-')}
listed = set(read_crates_sh())
print('missing:', ws - listed, 'extra:', listed - ws)

Try / catch

try:
    validate_order(...)
except ValidationError as e:
    for line in str(e).splitlines(): print('fix inventory:', line)

Prevention

When it happens

Trigger: Adding a new codewhale-* crate to the workspace without appending it to crates.sh; renaming or removing a crate without updating crates.sh; listing a crate in crates.sh that no longer exists or is not named codewhale-*.

Common situations: Release-day checklist misses the new crate; a crate is renamed (e.g. codewhale-core → codewhale-protocol) and crates.sh keeps the old name; crates.sh contains a typo.

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


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/b6385abb87003a24. Report an issue: GitHub.

Appendix: source

Thrown at scripts/release/validate-crate-publish-order.py:118

        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))

    positions = {name: index for index, name in enumerate(ordered_crates)}
    has_workspace_dependencies = {name: False for name in release_names}
    publish_edges: set[tuple[str, str, str]] = set()
    for dependent in release_names:
        dependencies = workspace_by_name[dependent].get("dependencies", [])
        if not isinstance(dependencies, list):
            raise ValidationError(f"Cargo metadata dependencies for {dependent} must be a list")
        for dependency in dependencies:
            if not isinstance(dependency, dict) or dependency.get("path") is None:
                continue
            dependency_name = dependency.get("name")
            if dependency_name not in workspace_by_name:
                continue
            has_workspace_dependencies[dependent] = True
            kind = dependency.get("kind") or "normal"
            # Cargo does not compile dev-dependencies while verifying a publish.
            # They may legitimately point back across the publication DAG.

View on GitHub (pinned to 433685b202)