{"record":{"id":"2d71a888e667600c","repo":"Hmbown/CodeWhale","slug":"dependent-depends-on-workspace-crate-dependency","errorCode":null,"errorMessage":"{dependent} depends on workspace crate {dependency_name} [{kind}], which is not in the codewhale-* release inventory","messagePattern":"(.+?) depends on workspace crate (.+?) \\[(.+?)\\], which is not in the codewhale-\\* release inventory","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"scripts/release/validate-crate-publish-order.py","lineNumber":140,"sourceCode":"    publish_edges: set[tuple[str, str, str]] = set()\n    for dependent in release_names:\n        dependencies = workspace_by_name[dependent].get(\"dependencies\", [])\n        if not isinstance(dependencies, list):\n            raise ValidationError(f\"Cargo metadata dependencies for {dependent} must be a list\")\n        for dependency in dependencies:\n            if not isinstance(dependency, dict) or dependency.get(\"path\") is None:\n                continue\n            dependency_name = dependency.get(\"name\")\n            if dependency_name not in workspace_by_name:\n                continue\n            has_workspace_dependencies[dependent] = True\n            kind = dependency.get(\"kind\") or \"normal\"\n            # Cargo does not compile dev-dependencies while verifying a publish.\n            # They may legitimately point back across the publication DAG.\n            if kind == \"dev\":\n                continue\n            if dependency_name not in positions:\n                raise ValidationError(\n                    f\"{dependent} depends on workspace crate {dependency_name} \"\n                    f\"[{kind}], which is not in the codewhale-* release inventory\"\n                )\n            publish_edges.add((dependency_name, dependent, str(kind)))\n\n    violations = sorted(\n        (\n            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(","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/validate-crate-publish-order.py#L122-L158","documentation":"A codewhale-* release crate has a path dependency on another workspace crate whose name is not in the codewhale-* release inventory -- i.e. the dependency is a workspace member not named with the codewhale- prefix, so it can never appear in the publication order. Dev-dependencies are exempt (cargo does not compile them during publish verification, so they may point backwards in the DAG); normal and build dependencies are not. The message names the dependent, the dependency, and the dependency kind.","triggerScenarios":"Adding a new internal support crate named without the prefix (e.g. 'my-utils') and path-depending on it from codewhale-tui; renaming an existing codewhale-* crate to drop the prefix while dependents still reference it by path; a build-dependency ('build' kind) on a non-codewhale workspace crate.","commonSituations":"Introducing helper crates without following the codewhale-* naming convention that the release inventory is built on.","solutions":["Rename the dependency crate to carry the codewhale- prefix (package.name in its Cargo.toml), update dependents, and add it to scripts/release/crates.sh before its dependents","Alternatively depend on the published crates.io version instead of a path dependency, if the support crate is released separately","If the dependency is genuinely test-only, move it to [dev-dependencies] so it is exempt from the DAG"],"exampleFix":"# crates/my-utils/Cargo.toml: before\n[package]\nname = \"my-utils\"\n\n# after (then add it to scripts/release/crates.sh)\n[package]\nname = \"codewhale-my-utils\"","handlingStrategy":"validation","validationCode":"# Before release, scan for non-codewhale path dependencies of release crates:\nimport json, subprocess\n\nmeta = json.loads(subprocess.run(\n    [\"cargo\", \"metadata\", \"--locked\", \"--format-version\", \"1\", \"--no-deps\"],\n    capture_output=True, text=True, check=True).stdout)\nby_name = {p[\"name\"]: p for p in meta[\"packages\"]}\nfor dependent in (n for n in by_name if n.startswith(\"codewhale-\")):\n    for dep in by_name[dependent].get(\"dependencies\", []):\n        if dep.get(\"path\") and dep.get(\"name\") in by_name \\\n                and (dep.get(\"kind\") or \"normal\") != \"dev\" \\\n                and not dep[\"name\"].startswith(\"codewhale-\"):\n            raise SystemExit(f\"{dependent} path-depends on non-release crate {dep['name']}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enforce the codewhale- prefix convention for every publishable workspace crate (repo convention check in CI)","Remember dev-dependencies are exempt but normal and build dependencies are not"],"tags":["release","cargo","dependencies","naming","python"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}