protocolbuffers / protocolbuffers/protobuf

MODULE.bazel: crate_universe usage without a lockfile breaks every `bazel mod` command for consumers

Open Beginner friendly
#29,866 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
72k
Forks
16.3k
Avg merge
1d 17h
Merged PRs (30d)
140

Description

What version of protobuf and what language are you using?

Version: v35.1 (and every version the BCR carries, through 36.2)
Language: Bazel module consumers of any language; the Rust rules are what triggers it

What operating system (Linux, Windows, ...) and version?

Linux (Debian), Bazel 8.x with bzlmod

What did you do?

In any Bazel workspace that reaches protobuf as a transitive module, which includes any workspace depending on rules_cc, and that also has rules_rust 0.73.0 or newer in its graph:

$ bazel mod graph
What did you expect to see?

The module graph, and exit 0.

What did you see instead?
ERROR: external/rules_rust+/crate_universe/extensions.bzl:621:17: Traceback (most recent call last):
	File "extensions.bzl", line 1200, column 37, in _crate_impl
		_generate_hub_and_spokes(
	File "extensions.bzl", line 621, column 17, in _generate_hub_and_spokes
		fail(("crate_universe extension call `{}` is in a non-root module " +
Error in fail: crate_universe extension call `crates` is in a non-root module but has no lockfile. Transitive crate_universe repositories must ship a `lockfile = ...` because repinning is not supported across module boundaries.
ERROR: error evaluating module extension @@rules_rust+//crate_universe:extension.bzl%crate
ERROR: Results may be incomplete as 1 extension failed.

Exit status 2. The graph still prints, so the failure is easy to miss in a terminal and impossible to miss in a script. bazel mod deps, explain, show_repo and show_extension fail the same way.

bazel build and bazel test are unaffected, because nothing in a consumer's build reaches protobuf's Rust crates. Only the module inspection commands break, which means the tool you reach for when you have a dependency question is the one that does not work.

Where it comes from

MODULE.bazel line 197:

crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate")
crate.spec(package = "googletest", version = ">0.0.0")
...
crate.from_specs()
use_repo(crate, crate_index = "crates")

crate.from_specs() is called with no lockfile. rules_rust 0.73 added a fail for exactly that in a non-root module, under a comment citing rules_rust#1738: a transitive module's lockfile cannot be repinned, so the extension refuses to proceed without one.

Suggested fix, one line

Mark the usage as what it is, a dependency of protobuf's own development:

-crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate")
+crate = use_extension("@rules_rust//crate_universe:extension.bzl", "crate", dev_dependency = True)

A non-root module's dev_dependency usages are not evaluated, so the check never runs for consumers. protobuf's own builds are unaffected: there protobuf is the root module, dev_dependency usages are evaluated as before, and the check passes for a root module with or without a lockfile.

Verified by overriding the module locally with that one line changed:

$ bazel mod graph --override_module=protobuf=/tmp/protobuf-patched
<root> (...)
├───platforms@1.1.0
...
exit 0

and again by serving a patched protobuf@35.1 entry from a local registry, after which bazel build of the same targets still succeeds.

The alternative is to ship lockfile = ... alongside crate.from_specs(), which is what the rules_rust message asks for and is the better answer if protobuf's Rust crates are meant to be usable by consumers. If they are not, the dev_dependency line says so and costs nothing.

Anything else we should know about your project / environment?

Found while answering a dependency question in an unrelated project, where the module graph could not be printed. Reported there as a workaround; this is the upstream report.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at MODULE.bazel line 197, where the crate_universe extension is declared without a lockfile, and review how rules_rust 0.73 handles non-root module extensions. Verify the change with bazel mod graph and related module inspection commands, then confirm that the existing build and test behavior remains unaffected.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
build-system
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
92/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.