You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
codegen: a descriptor set that DescriptorPool rejects generates code whose descriptor_pool() panics at first use #626
Codegen and DescriptorPool validate a FileDescriptorSet independently, and the pool enforces rules that codegen does not: a scalar field that also has a type_name (PoolError::UnexpectedTypeName), duplicate field numbers and names, invalid oneof indexes, malformed map entries, reserved-range and extension-range rules, and the rest of the PoolError enum (buffa-descriptor/src/pool.rs). protoc output satisfies all of them. A set passed to Config::descriptor_set or descriptor_set_bytes that was built by hand or by another tool may not.
With generate_reflection on, codegen embeds the set and emits
DescriptorPool::decode_with_options(FILE_DESCRIPTOR_SET_BYTES,&options).expect("buffa-codegen emitted a linkable FileDescriptorSet")
in each form of descriptor_pool() (buffa-codegen/src/reflect.rs). For a set the pool rejects, the build succeeds and the first reflective call in the consumer's process panics. The generated doc says a panic "indicates a codegen bug, not consumer input", which is wrong for these inputs.
The failure belongs at generation time. When reflection is on, generate_with_diagnostics can build a DescriptorPool from the same descriptors and return its error as a CodeGenError; the alternative is one validation pass shared by the two crates. buffa-codegen depends on buffa-descriptor without its reflect feature today, so the first option turns that feature on for the codegen toolchain.
I'd like to take this one. Reproduced on main at 1047169:
A hand-built set with one message p626.M whose int32 x = 1 also carries type_name: ".p626.M". generate with generate_reflection = true returns Ok (3 files, the descriptor_pool() with the expect is in the output).
DescriptorPool::decode on the bytes encode_fds_once produces for that set returns Err(UnexpectedTypeName { field: "p626.M.x", type_name: ".p626.M" }), so the generated descriptor_pool() panics on first call.
Plan, going with your first option:
In generate_with_diagnostics, when generate_reflection is on, link the same override-applied file_descriptors that get embedded with DescriptorPool::new and map a PoolError to a new CodeGenError variant that carries it, before any output is produced. Shared-pool mode embeds nothing in generate, so I'd run the same check there too, since the front-end embeds the same set.
Turn on buffa-descriptor's reflect feature in buffa-codegen. It is reflect = [], so it adds no crates, only compiles the pool module into the toolchain.
Fix the generated doc: the panic can still mean a codegen bug, but no longer "not consumer input" once this lands, so it would say the set was linked at generation time.
Tests: the UnexpectedTypeName case and a second PoolError that I've confirmed codegen lets through today, both failing on main, plus a check that reflection off still generates as before.
One question before I build it: should the link only run with reflection on, as the issue says, or always? With reflection off nothing embeds the set, so I'd keep it gated unless you want codegen to reject these sets regardless.
Activity
codegen: reject a message with two fields that share a field number (a…
descriptor: reject a field or extension typed as a map entry it does …
harshitwandhare commentedon Oct 28, 2026
I'd like to take this one. Reproduced on
mainat1047169:p626.Mwhoseint32 x = 1also carriestype_name: ".p626.M".generatewithgenerate_reflection = truereturnsOk(3 files, thedescriptor_pool()with theexpectis in the output).DescriptorPool::decodeon the bytesencode_fds_onceproduces for that set returnsErr(UnexpectedTypeName { field: "p626.M.x", type_name: ".p626.M" }), so the generateddescriptor_pool()panics on first call.Plan, going with your first option:
generate_with_diagnostics, whengenerate_reflectionis on, link the same override-appliedfile_descriptorsthat get embedded withDescriptorPool::newand map aPoolErrorto a newCodeGenErrorvariant that carries it, before any output is produced. Shared-pool mode embeds nothing ingenerate, so I'd run the same check there too, since the front-end embeds the same set.buffa-descriptor'sreflectfeature inbuffa-codegen. It isreflect = [], so it adds no crates, only compiles the pool module into the toolchain.UnexpectedTypeNamecase and a secondPoolErrorthat I've confirmed codegen lets through today, both failing onmain, plus a check that reflection off still generates as before.One question before I build it: should the link only run with reflection on, as the issue says, or always? With reflection off nothing embeds the set, so I'd keep it gated unless you want codegen to reject these sets regardless.