protocolbuffers / protocolbuffers/protobuf
`rust_proto_library` fails in downstream Bzlmod builds due to relative resolution of `//rust:use_upb_kernel`
@esrauchg is already working on this.
Since Aug 11, 2026.
- 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: main/v35.1
Language: Rust
What
supported operating system version
are you using (e.g. Linux, Windows) ?
Host / Target OS: Linux
What
supported runtime / compiler version
are you using (e.g. python version, gcc version)
Bazel Version: 9.2.0 (managed via bazelisk). See also MODULE.bazel below for rustc version. C/C++ compiler version seems mostly irrelavant as the issue is in the Bazel / Rust integration.
What did you do?
$ cd protobuf_repro_35
$ cat MODULE.bazel
module(
name = "protobuf_repro_35",
version = "0.0.1",
)
bazel_dep(name = "protobuf", version = "35.1")
bazel_dep(name = "rules_rust", version = "0.71.3")
bazel_dep(name = "rules_proto", version = "7.1.0")
rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
rust.toolchain(
edition = "2024",
versions = ["1.97.1"],
)
use_repo(rust, "rust_toolchains")
register_toolchains("@rust_toolchains//:all")
$ cat BUILD
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@protobuf//rust:defs.bzl", "rust_proto_library")
proto_library(
name = "foo_proto",
srcs = ["foo.proto"],
)
rust_proto_library(
name = "foo_rust_proto",
visibility = ["//visibility:public"],
deps = [":foo_proto"],
)
$ cat foo.proto
syntax = "proto3";
package foo;
message Bar {
string baz = 1;
}
$ bazelisk build //:foo_rust_proto
ERROR: no such package 'rust': BUILD file not found in any of the following directories. Add a BUILD file to a directory to mark it as a package.
- rust
ERROR: /usr/local/google/home/lukasza/src/protobuf_repro_35/BUILD:9:19: errors encountered resolving select() keys for //:foo_rust_proto
ERROR: Analysis of target '//:foo_rust_proto' failed; build aborted
INFO: Elapsed time: 0.257s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
ERROR: Build did NOT complete successfully
What did you expect to see
I expected the build to succeed.
What did you see instead?
The build failed - see the repro steps above.
Anything else we should know about your project / environment
Proposed Fix
The issue is that the rust_proto_library macro in @protobuf//rust:defs.bzl uses a raw string literal for the select key:
native.alias(
name = name + "_rust_proto",
actual = select({
"//rust:use_upb_kernel": name + "_upb_rust_proto",
"//conditions:default": name + "_cpp_rust_proto",
}),
**alias_args
)
In Bazel, raw string labels in macros are resolved relative to the caller's repository/package. When a downstream project calls rust_proto_library, Bazel looks for //rust:use_upb_kernel in
the downstream project instead of the @protobuf repository.
To fix this, the label should be wrapped in Label() to force it to resolve relative to the defining repository (@protobuf):
native.alias(
name = name + "_rust_proto",
actual = select({
- "//rust:use_upb_kernel": name + "_upb_rust_proto",
+ Label("//rust:use_upb_kernel"): name + "_upb_rust_proto",
"//conditions:default": name + "_cpp_rust_proto",
}),
**alias_args
)
According to Bazel documentation on Starlark Macros https://bazel.build/extending/macros#label-resolution:
A string literal is resolved as a label in the context of the package where the target is declared (the caller). If you want to refer to a target in the same package where the macro is
defined, you must use Label().
Using Label("//rust:use_upb_kernel") ensures that the label is resolved to @protobuf//rust:use_upb_kernel (or its canonical Bzlmod equivalent @@protobuf+//rust:use_upb_kernel) regardless of
which downstream module calls the macro.
Note on 36.0-rc2 Verification Blocker
An attempt was made to verify if this issue persists in the 36.0-rc2 release candidate. However, the build failed early during module resolution due to an independent Bzlmod configuration
issue in the protobuf module's own dependencies:
Error Output:
ERROR: .../external/rules_rust+/crate_universe/extensions.bzl:621:17:
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 i
not supported across module boundaries.
ERROR: Analysis of target '//:foo_rust_proto' failed; build aborted: error evaluating module extension @@rules_rust+//crate_universe:extension.bzl%crate
Technical Details of the Blocker:
• The protobuf module (v36.0-rc2) utilizes rules_rust's crate_universe extension transitively to manage its Rust dependencies.
• Under Bzlmod, when a non-root module (which protobuf is, from the perspective of a downstream project) calls crate_universe, it must supply a pre-generated lockfile via the lockfile
attribute. This is because Bazel does not support generating ("re-pinning") lockfiles for transitive dependencies across module boundaries.
• The protobuf v36.0-rc2 module appears to be missing this lockfile configuration in its transition to Bzlmod, which completely blocks downstream projects from using its Rust rules under
Bazel 8/9.
• Because of this blocker, we could not verify if the use_upb_kernel label resolution bug was fixed in 36.0-rc2, though static analysis suggests the macro implementation remains unchanged.
AI usage disclaimer
This bug report was created with the help of an AI agent. I have independently, manually verified (and cleaned up slightly) the main repro. OTOH the "Proposed Fix" and "Note on 36.0-rc2 Verification Blocker" are almost verbatim copies of AI agent's output.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.