protocolbuffers / protocolbuffers/protobuf

`rust_proto_library` fails in downstream Bzlmod builds due to relative resolution of `//rust:use_upb_kernel`

Open
#29,090 2 comments 0 reactions 1 assignee View on GitHub

@esrauchg is already working on this.

Since Aug 11, 2026.

bug rust
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

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.