Bzlmod Dependency Issues
Describe the bug
I'm having a heck of time with cel.dev/expr, cel-go, and a new bzlmod version of our repo.
First off, the error I'm seeing:
ERROR: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/gazelle++go_deps+com_github_google_cel_go/common/types/BUILD.bazel:8:11: no such package '@@[unknown repo 'dev_cel_expr' requested from @@gazelle++go_deps+com_github_google_cel_go]//': The repository '@@[unknown repo 'dev_cel_expr' requested from @@gazelle++go_deps+com_github_google_cel_go]' could not be resolved: No repository visible as '@dev_cel_expr' from repository '@@gazelle++go_deps+com_github_google_cel_go' and referenced by '@@gazelle++go_deps+com_github_google_cel_go//common/types:go_default_library'
It seems that Bazel itself has some dependency on cel.dev/expr via a bazel_dep on cel-spec. So what that means, if you an import "cel.dev/expr" in your code, Gazelle will actually place the dep in your BUILD.bazel as "@cel-spec//:go_default_library". Getting all the version to align to even get bzlmod happy is pretty tricky, but in that case I still can't get it building.
So the list of what I have:
- Using bzlmod in project with Bazel version 8.2.1
- Have a dep on
cel.dev/exprin one of my own packages - Also have a dep on
cel-goin one of my own packages rules_go 0.54.1gazelle 0.43.0
The incantation I'm at that has caused the above error:
MODULE.bazel
bazel_dep(
name = "cel-spec",
version = "0.23.0",
)
go.mod
require (
cel.dev/expr v0.23.0
github.com/google/cel-go v0.24.1
)
Honestly, this isn't the incantation I even want, but it's the only one I found that could make bzlmod happy, and it still doesn't work. Ideally I could just pull in latest versions.
Here's some examples of the run-around:
Run `go get github.com/google/[email protected]`
$ bazel run @rules_go//go -- get github.com/google/[email protected]
Computing main repo mapping:
Loading:
Loading: 0 packages loaded
bazel: Entering directory `/private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/execroot/_main/'
Analyzing: target @@rules_go+//go:go (0 packages loaded, 0 targets configured)
Analyzing: target @@rules_go+//go:go (0 packages loaded, 0 targets configured)
Analyzing: target @@rules_go+//go:go (19 packages loaded, 10305 targets configured)
INFO: Analyzed target @@rules_go+//go:go (92 packages loaded, 17359 targets configured).
INFO: Found 1 target...
bazel: Leaving directory `/private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/execroot/_main/'
Target @@rules_go+//go/tools/go_bin_runner:go_bin_runner up-to-date:
.bazel/bin/external/rules_go+/go/tools/go_bin_runner/bin/go
INFO: Elapsed time: 1.404s, Critical Path: 0.01s
INFO: 1 process: 11 action cache hit, 1 internal.
INFO: Build completed successfully, 1 total action
INFO: Running command line: .bazel/bin/external/rules_go+/go/tools/go_bin_runner/bin/go <args omitted>
go: upgraded cel.dev/expr v0.23.0 => v0.23.1
go: upgraded github.com/google/cel-go v0.24.1 => v0.25.0
rules_go: Running 'bazel mod tidy' since go.mod changed...
no actions running
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/rules_jvm_external+/private/lib/coordinates.bzl:76:18: Assuming com.google.code.gson:gson:jar:2.9.0 should be interpreted as com.google.code.gson:gson:2.9.0@jar
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/rules_jvm_external+/private/lib/coordinates.bzl:76:18: Assuming info.picocli:picocli:jar:4.6.3 should be interpreted as info.picocli:picocli:4.6.3@jar
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/gazelle+/internal/bzlmod/go_deps.bzl:607:40:
Mismatch between versions requested for Go module cel.dev/expr:
bazel_dep version (MODULE.bazel): 0.23.0 (as "cel-spec")
Go module version (go.mod): 0.23.1
Either ensure that you have
bazel_dep(module_name = "cel-spec", version = "0.23.1")
in your MODULE.bazel file or downgrade the Go module version via
bazel run @rules_go//go -- get cel.dev/[email protected]
Remove `bazel_dep` on `cel-spec`
bazel_dep(
name = "cel-spec",
version = "0.23.0",
)
$ bazel mod tidy
no actions running
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/rules_jvm_external+/private/extensions/maven.bzl:351:18: The maven repository 'maven' has contributions from multiple bzlmod modules, and will be resolved together: ["core", "grpc-java"]
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/rules_jvm_external+/private/lib/coordinates.bzl:76:18: Assuming com.google.code.gson:gson:jar:2.9.0 should be interpreted as com.google.code.gson:gson:2.9.0@jar
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/rules_jvm_external+/private/lib/coordinates.bzl:76:18: Assuming info.picocli:picocli:jar:4.6.3 should be interpreted as info.picocli:picocli:4.6.3@jar
DEBUG: /private/var/tmp/_bazel_jward/63162deb35ba6b2f678241a64a1d59bb/external/gazelle+/internal/bzlmod/go_deps.bzl:607:40:
Mismatch between versions requested for Go module cel.dev/expr:
bazel_dep version (MODULE.bazel): 0.15.0 (as "cel-spec")
Go module version (go.mod): 0.23.1
Either ensure that you have
bazel_dep(module_name = "cel-spec", version = "0.23.1")
in your MODULE.bazel file or downgrade the Go module version via
bazel run @rules_go//go -- get cel.dev/[email protected]
One maybe quite important note, I started having all of these issue the moment I tried to bring this into my MODULE.bazel:
bazel_dep(
name = "grpc",
version = "1.72.0",
)
That seems to be what made cel-spec get involved.
We recently removed rpc.Status as a dependency. I wonder if we just need to tag new releases for cel-spec and cel-go
On Mon, Jun 2, 2025, 4:59 PM Jarred Ward @.***> wrote:
jarreds left a comment (google/cel-go#1184) https://github.com/google/cel-go/issues/1184#issuecomment-2932936306
One maybe quite important note, I started having all of these issue the moment I tried to bring this into my MODULE.bazel:
bazel_dep( name = "grpc", version = "1.72.0", )
— Reply to this email directly, view it on GitHub https://github.com/google/cel-go/issues/1184#issuecomment-2932936306, or unsubscribe https://github.com/notifications/unsubscribe-auth/AADV7ZAZBRZKRT7E7WRL6TT3BTQNBAVCNFSM6AAAAAB6OHPRGCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDSMZSHEZTMMZQGY . You are receiving this because you are subscribed to this thread.Message ID: @.***>
Repro repo here https://github.com/jarreds/cel-go-repro
README.md has details on repro.
FWIW I was able to get this compiling at least by adding this to the go.mod:
replace cel.dev/expr v0.23.1 => cel.dev/expr v0.23.0
@jarreds Thank you so much for the report and the repro. I'm not sure what this could be, but at least we have a good documented case of working and non-working.
Same issue. Thanks for the repro and notes. FWIW, a similar error was discussed in https://github.com/bazel-contrib/bazel-gazelle/pull/2096 but using Gazelle v0.44.0+ (which has that change) does not fix the issue for me. Could be a red herring.
AFAICT, I was able to fix my build issue with this change, which kinda looks like the inverse of the Gazelle change I linked above. IMO cleaner than editing go.mod by hand since I like to regenerate that file with go mod tidy sometimes. Probably worth following up with that change to Gazelle since there was no repro attached to that.
Hm, your repro seems to work ok with Gazelle v0.42.0, then it breaks with Gazelle 0.43.0 - 0.45.0, even though that relevant-looking change was not present in 0.43.0. I'm confused, but I'm also at the end of my debugging budget given that a decent-enough fix is found.
The root cause is that there is a BCR module for the cel-spec repo, cel-go doesn't use it, but grpc does. That should be cleaned up: If cel-spec is somehow special so that Gazelle can only load it via go_deps with special directives, then those (and only those) directives should be added to gazelle's default set. Then the BCR module should be dropped as a dep by grpc and consumed as a Go module via go_deps instead.
Are you able to get in touch with the grpc maintainers?
The dependency graph looks something like this (irrelevant branches elided):
grpc
├── grpc-java
│ └── cel-spec
└── xds
└── cel-spec
So grpc is not directly dependent on cel-spec, and it seems the dependencies that are are using more than just the Go library that it provides, so using go_deps is not a good substitute. For instance, xds depends on these targets:
# Note that xds renames @cel-spec to @dev_cel.
@dev_cel//proto/cel/expr:checked.proto
@dev_cel//proto/cel/expr:checked_cc_proto
@dev_cel//proto/cel/expr:checked_go_proto
@dev_cel//proto/cel/expr:checked_proto
@dev_cel//proto/cel/expr:syntax.proto
@dev_cel//proto/cel/expr:syntax_cc_proto
@dev_cel//proto/cel/expr:syntax_go_proto
@dev_cel//proto/cel/expr:syntax_proto
It does not depend on @cel-spec//:expr or @cel-spec//:go_default_library, and it seems like grpc-java only depends on @cel-spec because of xds (it uses some strange vendoring for dependencies though, so my analysis might be off)
I'm not sure what can be done about this. It seems like the cel-spec Bazel module probably should have been narrower in scope: just cel-spec-proto or something, and require it's dependents to use Gazelle if they also need the Go library. However, reducing the scope would be a breaking change. I invite @TristonianJones (who I found listed as a maintainer for the @cel-spec module) to help think about this more :)
Hi @ouillie and @fmeum, I wish I could say that Bazel is second-nature to me, but alas, I end up with build configurations which work locally (after several hours of trying), but break dependencies.
Here's what I've been looking into ...
- I'm removing the google/rpc/status.proto dependency from cel-spec and will publish cel-spec v0.25.0
- I'll update cel-go to use the BCR bazel_dep for v0.25.0
My understanding is that these two changes will have the following effects:
- Removing the google/rpc/status.proto dep from cel-spec will remove transitive dependences on gRPC from the cel-spec repo. In other words, the spec will be completely self-contained.
- The bazel dep update on cel-go will "just work" to help reduce collisions for those who use cel-go.
I'm not sure this solves all issues though; however, I can work with the gRPC maintainers to update their reference to cel-spec and help clean up the mess if it does.
What do you think?
-Tristan
Thanks for looking into that. I'm also operating with an incomplete picture, mainly because Gazelle is still rather mysterious to me, but I think you're getting a couple things backward:
Removing the google/rpc/status.proto dep from cel-spec will remove transitive dependences on gRPC from the cel-spec repo. In other words, the spec will be completely self-contained.
The issue I and @jarreds were having was caused by the fact that grpc transitively depends on cel-spec (via xds), not the other way around.
I'll update cel-go to use the BCR bazel_dep ... The bazel dep update on cel-go will "just work" to help reduce collisions for those who use cel-go.
I believe the core problem is that the Bazel dependency cel-spec cannot co-exist with the Go dependency cel.dev/expr, which seems to make sense because they're both claiming to provide Go modules with the same name. You're suggesting we move away from the Go dependency and use the Bazel dependency only, but I believe @fmeum was suggesting that we actually use the Go dependency instead of the Bazel dependency. That would solve the problem for every Go module that transitively depends on cel.dev/expr, not just cel-go (although that looks to be the "main dependent").
Basically, I think that the cel-spec Bazel module should not provide a Go module at all. It should instead rely on Gazelle for the Go module, if it needs it at all. It can still provide the Protobuf rules, though. Those are not causing any issues, and it seems like that's the main value prop of the cel-spec Bazel repo in the first place: providing the language-agnostic Protobuf rules.
I see that both modules use the same source repo, so perhaps we just need to patch the Go-specific stuff out of the Bazel module as a BCR patch.
@ouillie I appreciate the detailed feedback. It's helpful to understand how things are consumed.
I'm concerned about the fact that cel-go depends on .pb.go files located in cel.dev/expr while the conformance tests rely on content in the cel-spec bzlmod dep since I'd like the cel-go module to work with both Bazel and go build.
I can make the cel-go repo depend on the bzlmod dep which seems to satisfy this constraint (both builds work), but I can't think of a way to go the other way around, shy of moving the .pb.go protos to another repository, like go-genproto does for googleapis
Ok, maybe @fmeum can verify the accuracy of my understanding of Gazelle:
Gazelle basically expects to be the only sheriff in town when it comes to managing Go module dependencies. It's important to remember that Gazelle generates BUILD files not just for your own Go packages, but for your dependencies, and all of their dependencies transitively. Let's say I have a Go library that depends on github.com/some/package, and github.com/some/package does not use Bazel at all; it's just a regular Go module. If github.com/some/package depends on cel.dev/expr, then Gazelle is going to try to generate its own BUILD files for github.com/some/package and cel.dev/expr (and every other transitive dependency). Gazelle wouldn't know or care if the cel-go Bazel module depends on the cel-spec Bazel module. Because there's a non-Bazel Go dependency in between me and cel.dev/expr, Gazelle is going to do things its own way.
Basically, this goes deeper than just fixing the build for the cel-go repo. The core of the problem is that the cel-spec Bazel module includes a go.mod file, but Gazelle should be the only thing managing Go module dependencies.
The one thing making this complicated is that fact that both the Bazel module and the Go module are published from the same source repo. You need that go.mod file and the generated .pb.go files in order to publish the Go module, but they're messing with the Bazel module. So, I suggested adding a Bzlmod patch like this to delete the go.mod and go.sum files and remove all the other Go-specific stuff from that repo before publishing it as a Bazel module. That patch would be kinda big and unwieldy, but I think it's necessary. The cel-spec Bazel module should not provide anything Go-specific. It should just provide the language-agnostic Protobuf files and rules. Everything else should just go through Gazelle (you don't have to change anything about how the Go module is published). cel-go should not depend on cel-spec. cel-go should rely on Gazelle to provide cel.dev/expr as a Go dependency, and that would include the generated .pb.go code.
But ya, would probably be cleaner to just have separate source repos.
Having the BCR modules also provide the Go targets is somewhat useful since it avoids version skew between the protos (coming from the Bazel module) and the generated Go code (coming from the Go module).
The simplest solution at this point would actually be for cel-go to depend on cel-spec as a Bazel module.
Ok, fair enough. Happy to help review / test this solution.
Thank you @fmeum and @ouillie, I'm so glad to have your help in weighing through the tradeoffs, and really appreciate your support. I'll update the cel-spec, BCR, and then cel-go ... might take a couple of days