{"record":{"id":"f03846b9aeb7fd40","repo":"Hmbown/CodeWhale","slug":"workspace-package-is-missing-a-name","errorCode":null,"errorMessage":"workspace package is missing a name","messagePattern":"workspace package is missing a name","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"scripts/release/validate-crate-publish-order.py","lineNumber":94,"sourceCode":"            \"Cargo metadata omits workspace package ids: \" + \", \".join(missing_ids)\n        )\n    return [packages_by_id[member] for member in members]\n\n\ndef validate_order(\n    packages: list[dict[str, Any]], ordered_crates: list[str]\n) -> tuple[str, dict[str, bool]]:\n    duplicate_crates = sorted(\n        {name for name in ordered_crates if ordered_crates.count(name) > 1}\n    )\n    if duplicate_crates:\n        raise ValidationError(\n            \"publish package list contains duplicates: \" + \", \".join(duplicate_crates)\n        )\n\n    names = [package.get(\"name\") for package in packages]\n    if any(not isinstance(name, str) or not name for name in names):\n        raise ValidationError(\"workspace package is missing a name\")\n    if len(set(names)) != len(names):\n        raise ValidationError(\"Cargo metadata contains duplicate workspace package names\")\n\n    versions = sorted({package.get(\"version\") for package in packages})\n    if len(versions) != 1 or not isinstance(versions[0], str) or not versions[0]:\n        rendered = \", \".join(str(version) for version in versions)\n        raise ValidationError(f\"workspace packages have mixed versions: {rendered}\")\n\n    workspace_by_name = {package[\"name\"]: package for package in packages}\n    release_names = sorted(\n        name for name in workspace_by_name if name.startswith(\"codewhale-\")\n    )\n    ordered_set = set(ordered_crates)\n    missing = sorted(set(release_names) - ordered_set)\n    extra = sorted(ordered_set - set(release_names))\n    if missing or extra:\n        messages = []\n        if missing:","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/validate-crate-publish-order.py#L76-L112","documentation":"At least one workspace package record has a 'name' that is missing, not a string, or empty. cargo metadata always emits a package name, so this is an integrity guard that fires on malformed or hand-built metadata rather than on a healthy workspace.","triggerScenarios":"A --metadata-file fixture whose package object omits 'name' or sets it to null/empty; a package dict replaced by a non-dict would be skipped by the id filter, but a dict with id and no name triggers this.","commonSituations":"Writing unit-test fixtures for the validator and forgetting the name field on a synthetic package.","solutions":["Regenerate the fixture from real output: cargo metadata --locked --format-version 1 --no-deps","Or add a non-empty string 'name' to the malformed package entry in the fixture"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def packages_all_named(packages: list) -> bool:\n    return all(isinstance(p, dict) and isinstance(p.get(\"name\"), str) and p[\"name\"] for p in packages)","tryCatchPattern":null,"preventionTips":["Generate synthetic fixtures from real cargo metadata output rather than hand-writing package dicts"],"tags":["json","validation","cargo","fixtures","python"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}