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

unknown field

Error message

unknown field

What it means

serde_multikey's attribute options are parsed by MultiKeyOption::parse, which accepts only a known set of identifiers (e.g. `fields`). Any other identifier in the attribute args produces this compile error pointing at the unknown identifier.

Solutions

  1. Use the supported option name `fields(...)` with a comma-separated list of named field configs.
  2. Check the quickwit-macros documentation/tests for the exact attribute grammar and fix typos.

Example fix

// before
#[serde_multikey(field(value))]
// after
#[serde_multikey(fields(value))]
Defensive patterns

Strategy: validation

Validate before calling

// Only supported attribute option is `fields`:
// #[serde_multikey(fields(<name>[(into = .., try_from = ..)], ...))]

Prevention

When it happens

Trigger: Writing an unrecognized option inside #[serde_multikey(...)], e.g. a misspelled `field` instead of `fields`, or an option name that does not exist in the macro grammar.

Common situations: Typos in attribute options; copying attribute syntax from other serde macros (like #[serde(...)] options) that serde_multikey does not support.

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/cd89f9477e3bd565. Report an issue: GitHub.

Appendix: source

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

    fn parse(input: ParseStream) -> Result<Self, Error> {
        let ident: Ident = input.parse()?;
        match ident.to_string().as_str() {
            "serializer" => {
                input.parse::<Token![=]>()?;
                Ok(MultiKeyOption::Serializer(input.parse::<Path>()?))
            }
            "deserializer" => {
                input.parse::<Token![=]>()?;
                Ok(MultiKeyOption::Deserializer(input.parse::<Path>()?))
            }
            "fields" => {
                input.parse::<Token![=]>()?;
                let content;
                parenthesized!(content in input);
                let fields = content.parse_terminated(Field::parse_named, Token![,])?;
                Ok(MultiKeyOption::Fields(fields.into_iter().collect()))
            }
            _ => Err(Error::new(ident.span(), "unknown field")),
        }
    }
}

impl Parse for MultiKeyOptions {
    fn parse(input: ParseStream) -> Result<Self, Error> {
        let mut res = MultiKeyOptions {
            main_field_name: Ident::new("tmp_name", Span::call_site()),
            deserializer: None,
            serializer: None,
            proxy_fields: Vec::new(),
        };

        let options = Punctuated::<MultiKeyOption, Token![,]>::parse_terminated(input)?;
        for option in options {
            match option {
                MultiKeyOption::Deserializer(path) => {
                    if res.deserializer.is_none() {

View on GitHub (pinned to a39730c5cd)