{"record":{"id":"ee6edd93bb68aee4","repo":"Hmbown/CodeWhale","slug":"crate-publication-order-is-not-topological-dep","errorCode":null,"errorMessage":"crate publication order is not topological:\n  {dependent} (position {positions[dependent] + 1}) depends on {dependency} (position {positions[dependency] + 1}) [{kind}]\nMove every workspace dependency before its dependent in scripts/release/crates.sh.","messagePattern":"crate publication order is not topological:\n  (.+?) \\(position (.+?)\\) depends on (.+?) \\(position (.+?)\\) \\[(.+?)\\]\nMove every workspace dependency before its dependent in scripts/release/crates\\.sh\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"critical","filePath":"scripts/release/validate-crate-publish-order.py","lineNumber":166,"sourceCode":"            dependency,\n            dependent,\n            kind,\n        )\n        for dependency, dependent, kind in publish_edges\n        if positions[dependency] >= positions[dependent]\n    )\n    if violations:\n        lines = [\"crate publication order is not topological:\"]\n        for dependency, dependent, kind in violations:\n            lines.append(\n                f\"  {dependent} (position {positions[dependent] + 1}) depends on \"\n                f\"{dependency} (position {positions[dependency] + 1}) [{kind}]\"\n            )\n        lines.append(\n            \"Move every workspace dependency before its dependent in \"\n            \"scripts/release/crates.sh.\"\n        )\n        raise ValidationError(\"\\n\".join(lines))\n\n    return versions[0], has_workspace_dependencies\n\n\ndef main() -> int:\n    args = parse_args()\n    try:\n        packages = workspace_packages(load_metadata(args.metadata_file))\n        version, dependency_flags = validate_order(packages, args.crates)\n    except ValidationError as error:\n        print(error, file=sys.stderr)\n        return 1\n\n    print(f\"version\\t{version}\\t\")\n    for name in sorted(dependency_flags):\n        print(f\"crate\\t{name}\\t{1 if dependency_flags[name] else 0}\")\n    return 0\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/validate-crate-publish-order.py#L148-L184","documentation":"The maintained publication order violates dependency topology: for at least one edge, the dependency sits at the same or a later 1-based position than the crate that depends on it (positions come from the index in the positional crates list). Publishing in that order fails crates.io verification because the dependency's version is not published yet. Each violation is listed with both positions and the dependency kind, and the fix location is named: scripts/release/crates.sh.","triggerScenarios":"A newly added crate was appended to the end of the crates.sh list even though existing crates depend on it; entries were reordered during an edit; a dependency edge was introduced (crate A now path-depends on crate B) without moving B above A.","commonSituations":"Release validation after adding a mid-stack crate or after dependency restructuring between workspace crates.","solutions":["For every edge in the message, move the dependency crate above its dependent in scripts/release/crates.sh","Re-run scripts/release/validate-crate-publish-order.py with the list to confirm the topology is clean","Cross-check workspace deps when in doubt: cargo tree -p <dependent> -e normal,build"],"exampleFix":"# scripts/release/crates.sh: before (codewhale-tui depends on codewhale-release)\ncrates=(codewhale-protocol codewhale-tui codewhale-release codewhale-cli)\n\n# after\ncrates=(codewhale-protocol codewhale-release codewhale-tui codewhale-cli)","handlingStrategy":"validation","validationCode":"# Verify the order is topological before invoking the validator:\npositions = {name: i for i, name in enumerate(ordered_crates)}\nviolations = [\n    (dep, dependent)\n    for dependent in release_names\n    for dep in workspace_path_deps(dependent)   # names from cargo metadata, non-dev\n    if positions.get(dep, -1) >= positions[dependent]\n]\nassert not violations, f\"reorder crates.sh: {violations}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When inserting a new crate, place it above every crate that path-depends on it -- cargo tree -p <crate> shows workspace deps","Never append to the end of the publish list without checking dependents"],"tags":["release","topological-sort","cargo","publishing","python"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}