Title: [BUG] CelValue runtime path mishandles fixed32/fixed64 and FieldMask field access · Issue #1075 · cel-expr/cel-java · GitHub
Open Graph Title: [BUG] CelValue runtime path mishandles fixed32/fixed64 and FieldMask field access · Issue #1075 · cel-expr/cel-java
X Title: [BUG] CelValue runtime path mishandles fixed32/fixed64 and FieldMask field access · Issue #1075 · cel-expr/cel-java
Description: Describe the bug My motivation is to build support for protokt (alternate protobuf codegen + runtime) in protovalidate-java, which uses CEL. I think I've encountered two independent bugs in the planner runtime; both surface when CEL navi...
Open Graph Description: Describe the bug My motivation is to build support for protokt (alternate protobuf codegen + runtime) in protovalidate-java, which uses CEL. I think I've encountered two independent bugs in the pla...
X Description: Describe the bug My motivation is to build support for protokt (alternate protobuf codegen + runtime) in protovalidate-java, which uses CEL. I think I've encountered two independent bugs in the...
Opengraph URL: https://github.com/cel-expr/cel-java/issues/1075
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[BUG] CelValue runtime path mishandles fixed32/fixed64 and FieldMask field access","articleBody":"**Describe the bug**\n\nMy motivation is to build support for protokt (alternate protobuf codegen + runtime) in protovalidate-java, which uses CEL.\n\nI think I've encountered two independent bugs in the planner runtime; both surface when CEL navigates a `com.google.protobuf.Message` whose conversion goes through `ProtoCelValueConverter`: \n\n1. proto `fixed32`/`fixed64` fields resolve as signed int, breaking `uint` overloads: the CEL spec maps proto `fixed32`/`fixed64` to CEL `uint`, and the `CelValue` path via `ProtoCelValueConverter.fromProtoMessageFieldToCelValue` does not: it has cases for `UINT32`/`UINT64` but not `FIXED32`/`FIXED64`, so those fall through to `normalizePrimitive` and surface as `Integer`/`Long`.\n\n2. `FieldMask`-typed fields can't be navigated as messages: `BaseProtoCelValueConverter.fromWellKnownProto` converts `FieldMask` to a comma-separated string of its paths, which is different from cel-go and cel-java's `ProtoLiteAdapter.adaptValueToWellKnownProto`.\n\n**To Reproduce**\nCheck which components this affects:\n\n- [ ] parser\n- [ ] checker\n- [x] runtime\n\nReproducers (in Kotlin to get dependencies inline):\n\n1.\n ```kotlin\n @file:Repository(\"https://repo1.maven.org/maven2\")\n @file:DependsOn(\"dev.cel:cel:0.13.0\")\n @file:DependsOn(\"com.google.protobuf:protobuf-java:4.30.1\")\n \n import com.google.protobuf.DescriptorProtos.DescriptorProto\n import com.google.protobuf.DescriptorProtos.FieldDescriptorProto\n import com.google.protobuf.DescriptorProtos.FileDescriptorProto\n import com.google.protobuf.Descriptors.FileDescriptor\n import com.google.protobuf.DynamicMessage\n import dev.cel.bundle.CelFactory\n import dev.cel.common.types.StructTypeReference\n \n // A minimal one-field message: `Msg { fixed32 f = 1; }`, built from a runtime\n // descriptor so the reproducer needs no .proto compilation.\n val fileProto =\n FileDescriptorProto.newBuilder()\n .setName(\"repro.proto\")\n .setSyntax(\"proto3\")\n .addMessageType(\n DescriptorProto.newBuilder()\n .setName(\"Msg\")\n .addField(\n FieldDescriptorProto.newBuilder()\n .setName(\"f\")\n .setNumber(1)\n .setType(FieldDescriptorProto.Type.TYPE_FIXED32)\n .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)\n )\n )\n .build()\n \n val fileDescriptor = FileDescriptor.buildFrom(fileProto, arrayOf())\n val msgDescriptor = fileDescriptor.findMessageTypeByName(\"Msg\")\n \n val cel =\n CelFactory.plannerCelBuilder()\n .addMessageTypes(msgDescriptor)\n .addVar(\"msg\", StructTypeReference.create(\"Msg\"))\n .build()\n \n // The checker types a proto fixed32 field as CEL `uint`; `msg.f \u003e 5u` type-checks.\n val ast = cel.compile(\"msg.f \u003e 5u\").ast\n val program = cel.createProgram(ast)\n \n val msg =\n DynamicMessage.newBuilder(msgDescriptor)\n .setField(msgDescriptor.findFieldByNumber(1), 6)\n .build()\n \n val result = program.eval(mapOf(\"msg\" to msg))\n println(\"msg.f \u003e 5u -\u003e $result\")\n check(result == true) { \"expected true\" }\n println(\"OK\")\n ```\n\n Throws `dev.cel.runtime.CelEvaluationException: evaluation error at \u003cinput\u003e:6: No matching overload for function '_\u003e_'. Overload candidates: greater_uint64.`. Potential fix: https://github.com/google/cel-java/pull/1073\n\n2. \n ```kotlin\n @file:Repository(\"https://repo1.maven.org/maven2\")\n @file:DependsOn(\"dev.cel:cel:0.13.0\")\n @file:DependsOn(\"com.google.protobuf:protobuf-java:4.30.1\")\n \n import com.google.protobuf.DescriptorProtos.DescriptorProto\n import com.google.protobuf.DescriptorProtos.FieldDescriptorProto\n import com.google.protobuf.DescriptorProtos.FileDescriptorProto\n import com.google.protobuf.Descriptors.FileDescriptor\n import com.google.protobuf.DynamicMessage\n import com.google.protobuf.FieldMask\n import dev.cel.bundle.CelFactory\n import dev.cel.common.types.StructTypeReference\n \n // A minimal one-field message: `Msg { google.protobuf.FieldMask m = 1; }`.\n val fileProto =\n FileDescriptorProto.newBuilder()\n .setName(\"repro.proto\")\n .setSyntax(\"proto3\")\n .addDependency(\"google/protobuf/field_mask.proto\")\n .addMessageType(\n DescriptorProto.newBuilder()\n .setName(\"Msg\")\n .addField(\n FieldDescriptorProto.newBuilder()\n .setName(\"m\")\n .setNumber(1)\n .setType(FieldDescriptorProto.Type.TYPE_MESSAGE)\n .setTypeName(\".google.protobuf.FieldMask\")\n .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)\n )\n )\n .build()\n \n val fileDescriptor =\n FileDescriptor.buildFrom(fileProto, arrayOf(FieldMask.getDescriptor().file))\n val msgDescriptor = fileDescriptor.findMessageTypeByName(\"Msg\")\n \n val cel =\n CelFactory.plannerCelBuilder()\n .addMessageTypes(msgDescriptor)\n .addVar(\"msg\", StructTypeReference.create(\"Msg\"))\n .build()\n \n // `msg.m.paths` selects the repeated `paths` field of the FieldMask.\n val ast = cel.compile(\"msg.m.paths\").ast\n val program = cel.createProgram(ast)\n \n val msg =\n DynamicMessage.newBuilder(msgDescriptor)\n .setField(\n msgDescriptor.findFieldByNumber(1),\n FieldMask.newBuilder().addPaths(\"a\").addPaths(\"b\").build()\n )\n .build()\n \n val result = program.eval(mapOf(\"msg\" to msg))\n println(\"msg.m.paths -\u003e $result\")\n check(result == listOf(\"a\", \"b\")) { \"expected [a, b]\" }\n println(\"OK\")\n ```\n\n Throws `dev.cel.runtime.CelEvaluationException: evaluation error at \u003cinput\u003e:5: Error resolving field 'paths'. Field selections must be performed on messages or maps.`. Potential fix: https://github.com/google/cel-java/pull/1074\n\n**Additional context**\nFor the full context see https://github.com/bufbuild/protovalidate-java/pull/202 and https://github.com/open-toast/protokt/pull/402\n","author":{"url":"https://github.com/andrewparmet","@type":"Person","name":"andrewparmet"},"datePublished":"2026-06-02T16:11:59.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/1075/cel-java/issues/1075"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:4521687c-c5c8-21da-a463-60e48d3cb906 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | A7B0:14011B:2D5A59C:3F54921:6A4F66C8 |
| html-safe-nonce | 02b2db2e881e1a9882e0e0889e70dd15ee8ed16dad55a3d2bef14dc70af82394 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBN0IwOjE0MDExQjoyRDVBNTlDOjNGNTQ5MjE6NkE0RjY2QzgiLCJ2aXNpdG9yX2lkIjoiNzgxNDAwNDUwOTMwMzA3MjQ1NiIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 93c6675a601ff98b431f9b65c4f10bf4320b3c1a409cf7afbe8636fba1306245 |
| hovercard-subject-tag | issue:4573087665 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/cel-expr/cel-java/1075/issue_layout |
| twitter:image | https://opengraph.githubassets.com/73e235680342f5e7e176d3e9ee52201c053c27184784f401901cc1679bf42d36/cel-expr/cel-java/issues/1075 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/73e235680342f5e7e176d3e9ee52201c053c27184784f401901cc1679bf42d36/cel-expr/cel-java/issues/1075 |
| og:image:alt | Describe the bug My motivation is to build support for protokt (alternate protobuf codegen + runtime) in protovalidate-java, which uses CEL. I think I've encountered two independent bugs in the pla... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | andrewparmet |
| hostname | github.com |
| expected-hostname | github.com |
| None | b92d11c0aa4a77d54ef4af1078b6a15fb5a70a215b30c4ecf28889d5a8e656d9 |
| turbo-cache-control | no-preview |
| go-import | github.com/cel-expr/cel-java git https://github.com/cel-expr/cel-java.git |
| octolytics-dimension-user_id | 186625994 |
| octolytics-dimension-user_login | cel-expr |
| octolytics-dimension-repository_id | 587078119 |
| octolytics-dimension-repository_nwo | cel-expr/cel-java |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 587078119 |
| octolytics-dimension-repository_network_root_nwo | cel-expr/cel-java |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 4b249b445842943ed31549e027f57a8ade9881ed |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width