quickwit-oss/quickwit · error · proc-macro compile error

`serde_multikey` was applied multiple time to the same field

Error message

`serde_multikey` was applied multiple time to the same field

What it means

This compile-time proc-macro error comes from quickwit's custom `#[serde_multikey(...)]` attribute. The `parse_attributes` helper partitions a field's attributes and requires at most one `serde_multikey`; applying it more than once to the same field is ambiguous (which set of options should win?), so the macro emits a syn::Error pointing at the last duplicate occurrence.

Source

Thrown at quickwit/quickwit-macros/src/lib.rs:463

        if res.proxy_fields.is_empty() {
            todo!("throw error")
        }

        Ok(res)
    }
}

fn parse_attributes(
    attributes: Vec<Attribute>,
    field_name: &Ident,
) -> Result<(Option<MultiKeyOptions>, Vec<Attribute>), Error> {
    let (mut multikey_attributes, normal_attributes): (Vec<_>, _) = attributes
        .into_iter()
        .partition(|attr| attr.path().is_ident("serde_multikey"));

    if multikey_attributes.len() > 1 {
        let last = multikey_attributes.last().unwrap();
        return Err(Error::new(
            last.pound_token.spans[0],
            "`serde_multikey` was applied multiple time to the same field",
        ));
    }
    let options = if let Some(multikey_attribute) = multikey_attributes.pop() {
        let Meta::List(meta_list) = multikey_attribute.meta else {
            return Err(Error::new(
                multikey_attribute.pound_token.spans[0],
                "`serde_multikey` require list-style arguments",
            ));
        };
        let mut options: MultiKeyOptions = syn::parse2(meta_list.tokens)?;
        options.main_field_name = field_name.clone();
        Some(options)
    } else {
        None
    };

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Remove the duplicate `#[serde_multikey(...)]` attribute from the field, keeping only one.
  2. Merge the two attribute argument lists into a single `#[serde_multikey(...)]` if both sets of options are needed.
  3. If the duplicate came from a macro or code generator you control, deduplicate the attribute before emitting the struct.

Example fix

// before
#[serde_multikey(main_key = "a", sub_key = "b")]
#[serde_multikey(main_key = "a", sub_key = "c")]
my_field: MyType,
// after
#[serde_multikey(main_key = "a", sub_key = "c")]
my_field: MyType,
Defensive patterns

Strategy: validation

Validate before calling

// compile-time: ensure each field carries at most one serde_multikey attribute
let dupes = fields.iter().filter(|f| f.attrs.iter().filter(|a| a.path().is_ident("serde_multikey")).count() > 1).count();
assert_eq!(dupes, 0, "duplicate serde_multikey attribute");

Prevention

When it happens

Trigger: Compiling a struct derived via the proxy-struct macro (generate_proxy_struct) where a single field is annotated with two or more `#[serde_multikey(...)]` attributes.

Common situations: Merging code from two branches that each added `serde_multikey` to the same field; copy-pasting an attribute line and forgetting to remove the original; mechanically adding the attribute without noticing it was already present.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/5e5a3ce1da3c2171. Report an issue: GitHub.