quickwit-oss/quickwit · error · proc-macro compile error
`serde_multikey` was applied to a tuple-struct or an empty s
Error message
`serde_multikey` was applied to a tuple-struct or an empty struct
What it means
generate_proxy_struct builds a proxy struct mirroring the target's fields, which requires named fields (Fields::Named). Tuple structs, unit structs, and structs with unnamed fields cannot be mirrored, so the macro fails compilation with this message.
Source
Thrown at quickwit/quickwit-macros/src/lib.rs:157
let proxy_ident = Ident::new(&format!("__MultiKey{}", input.ident), input.ident.span());
input.ident = proxy_ident.clone();
input.vis = Visibility::Inherited;
// TODO wait for https://github.com/juhaku/utoipa/issues/704 to re-enable
// input.attrs.append(&mut Attribute::parse_outer
// .parse_str(&"#[doc(hidden)]")
// .unwrap());
let (ser, de) = get_ser_de(&input.attrs)?;
let mut pass_through = Vec::<Ident>::new();
let mut final_fields = Punctuated::<Field, Token![,]>::new();
let mut try_from_conv = Vec::<TokenStream2>::new();
let mut into_pre_conv = Vec::<TokenStream2>::new();
let mut into_in_conv = Vec::<TokenStream2>::new();
let Fields::Named(FieldsNamed { brace_token, named }) = input.fields else {
return Err(Error::new(
Span::call_site(),
"`serde_multikey` was applied to a tuple-struct or an empty struct",
));
};
for pair in named.into_pairs() {
let (mut field, ponct) = pair.into_tuple();
// we are in a "normal" struct, not a tuple-struct, unwrap is fine.
let field_name = field.ident.clone().unwrap();
let (field_config, attrs) = parse_attributes(field.attrs, &field_name)?;
field.attrs = attrs;
if let Some(field_config) = field_config {
let value = Ident::new("value", Span::call_site());
for field in &field_config.proxy_fields {
final_fields.push(field.clone());
}
match (ser, field_config.get_into(&value)) {View on GitHub (pinned to a39730c5cd)
Solutions
- Convert the struct to use named fields, e.g. `struct Wrapper { value: String }`.
- Remove the #[serde_multikey] attribute if multi-key behavior is not actually needed.
Example fix
// before
#[serde_multikey(fields(v))]
struct Wrapper(String);
// after
#[derive(Serialize, Deserialize)]
#[serde_multikey(fields(v))]
struct Wrapper { v: String } Defensive patterns
Strategy: validation
Validate before calling
// serde_multikey requires named fields; verify struct shape:
// struct Good { key: String } // OK
// struct Bad(String); // NOT supported
// struct Unit; // NOT supported Prevention
- Use named-field structs with serde_multikey
- Avoid converting multikey structs to newtype/tuple form during refactors
- If you need a newtype, drop the attribute and write serde impls manually
When it happens
Trigger: Applying #[serde_multikey(...)] to a tuple struct like `struct Wrapper(String);`, a unit struct `struct Unit;`, or any struct without named fields.
Common situations: Trying to make a newtype wrapper multi-key-capable; refactoring a named struct into a tuple struct while keeping the attribute.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- `serde_multikey` was applied to a non Serialize/Deserialize
- structure implement serialize but no serializer defined
- structure doesn't implement serialize but a serializer is de
- structure implement deserialize but no deserializer defined
- structure doesn't implement deserialize but a deserializer i
AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08).
Data as JSON: /api/errors/4b45e20d8fabad60.
Report an issue: GitHub.