quaint-telephone-89068
07/13/2026, 4:19 PMpants.backend.codegen.protobuf.java reads the generic ProtobufGrpcToggleField (available on both protobuf_source and protobuf_sources targets, regardless of which codegen backend is active) to decide whether to (a) enable gRPC Java stub generation and (b) inject the grpc-java runtime (grpc-netty-shaded, grpc-protobuf, grpc-stub, org.apache.tomcat:annotations-api) as an inferred dependency:
• src/python/pants/backend/codegen/protobuf/java/rules.py:163-171 — gates the protoc-gen-grpc-java plugin invocation on request.protocol_target.get(ProtobufGrpcToggleField).value.
• src/python/pants/backend/codegen/protobuf/java/dependency_inference.py:29-38,126-141 — ProtobufJavaRuntimeDependencyInferenceFieldSet requires ProtobufGrpcToggleField, and infer_protobuf_java_runtime_dependency conditionally adds the grpc-java runtime coordinates when request.field_set.grpc.value is set.
pants.backend.codegen.protobuf.scala never reads this field:
• src/python/pants/backend/codegen/protobuf/scala/rules.py:228 — generate_scala_from_protobuf always invokes the ScalaPB shim with a bare f"--scala_out={output_dir}". ScalaPB's own codegen supports a colon-separated modifier on --scala_out (--scala_out=grpc:<dir>) that turns on its built-in *Grpc.scala service-stub generation — sbt-protoc/ScalaPB passes this by default whenever a .proto declares a service, but Pants's Scala backend has no code path that ever adds it. ProtobufGrpcToggleField isn't even imported in this file.
• src/python/pants/backend/codegen/protobuf/scala/dependency_inference.py:28,79-88 — ScalaPBRuntimeDependencyInferenceFieldSet.required_fields is (ProtobufDependenciesField, JvmResolveField) only, and infer_scalapb_runtime_dependency unconditionally returns just the base scalapb-runtime_<binary_version> artifact. There's no equivalent of the Java backend's grpc-runtime injection, so even if (1) were fixed, generated *Grpc.scala files referencing scalapb.grpc.* / io.grpc.* would fail to compile with object grpc is not a member of package scalapb / object io is not a member of package <root>.
The net effect: protobuf_sources(grpc=True) on a target resolved by the Scala backend silently produces plain message classes with no service stubs and no gRPC runtime dependency — no error, no warning, just nothing happens. This is surprising because the field already exists generically on `protobuf_source`/`protobuf_sources` and visibly works for the Java backend, so grpc=True looks like supported, portable behavior. It's a feature-parity gap between the two backends, not a missing feature.
Pants version
Confirmed present as of main (2.33.0a0 in progress) and 2.32.0. Introduced when ScalaPB codegen/dependency-inference were added (#13853, #14898) — those predate ProtobufGrpcToggleField support even in the Java backend and were never revisited when Java gained it.
OS
N/A (backend logic bug, not platform-specific)
Additional info
• `protobuf_source`/`protobuf_sources`' ProtobufGrpcToggleField is defined once, generically, in pants/backend/codegen/protobuf/target_types.py and consumed per-backend; it is not itself backend-specific.
• A minimal repro: a protobuf_sources(grpc=True) target whose .proto declares a service, resolved once under a JVM resolve with the Java backend active and once with the Scala backend active. Java backend: generates FooServiceGrpc.java and injects grpc-java coordinates. Scala backend: generates only Foo.scala (message classes), no FooServiceGrpc.scala, no `scalapb-runtime-grpc`/`io.grpc.*` dependency — grpc=True has zero observable effect.
• I have a candidate fix (mirrors the exact pattern in pants.backend.codegen.protobuf.java.dependency_inference) and am happy to open a PR.
pantsbuild/pantsquaint-telephone-89068
08/07/2026, 6:46 PM