{"record":{"id":"1693348bdd308802","repo":"quickwit-oss/quickwit","slug":"the-attribute-can-only-be-applied-to-struct","errorCode":null,"errorMessage":"the attribute can only be applied to struct","messagePattern":"the attribute can only be applied to struct","errorType":"exception","errorClass":"proc-macro compile error","httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-macros/src/lib.rs","lineNumber":37,"sourceCode":"use quote::quote;\nuse syn::parse::{Parse, ParseStream, Parser};\nuse syn::punctuated::Punctuated;\nuse syn::{\n    Attribute, Error, Field, Fields, FieldsNamed, Ident, ItemStruct, Meta, Path, Token, Visibility,\n    parenthesized,\n};\n\n#[proc_macro_attribute]\npub fn serde_multikey(attr: TokenStream, item: TokenStream) -> TokenStream {\n    match serde_multikey_inner(attr, item) {\n        Ok(ts) => ts,\n        Err(e) => e.to_compile_error().into(),\n    }\n}\n\nfn serde_multikey_inner(_attr: TokenStream, item: TokenStream) -> Result<TokenStream, Error> {\n    let Ok(input) = syn::parse::<ItemStruct>(item) else {\n        return Err(Error::new(\n            Span::call_site(),\n            \"the attribute can only be applied to struct\",\n        ));\n    };\n\n    let main_struct = generate_main_struct(input.clone())?;\n\n    let proxy_struct = generate_proxy_struct(input)?;\n\n    Ok(quote!(\n    #main_struct\n    #proxy_struct\n    )\n    .into())\n}\n\n/// Generate the main struct. It's a copy of the original struct, but with most\n/// ser/de attributes removed, and serde try_from/into `__MultiKey{}` added.","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-macros/src/lib.rs#L19-L55","documentation":"serde_multikey is a proc-macro attribute that only makes sense on a struct declaration. serde_multikey_inner parses its input token stream as syn::ItemStruct and, if parsing fails (the item is an enum, union, fn, etc.), emits this compile error at the call site.","triggerScenarios":"Applying #[serde_multikey(...)] to any non-struct item: an enum, type alias, function, module, or impl block.","commonSituations":"Developer intends a multi-key struct but attaches the attribute to the wrong item in the file, or applies it above a module/enum during refactoring.","solutions":["Move the #[serde_multikey] attribute onto the struct declaration that should gain multi-key serde behavior.","If the target should be an enum, do not use serde_multikey; use plain serde derives instead."],"exampleFix":"// before\n#[serde_multikey(fields(key))]\nenum KeyKind { A }\n// after\n#[derive(Serialize, Deserialize)]\n#[serde_multikey(fields(key))]\nstruct KeyKind { key: String }","handlingStrategy":"validation","validationCode":"// Compile-time guard: the macro only accepts structs.\n// Verify the target is a struct before adding the attribute:\n// struct MyStruct { ... }  // <-- attribute goes here, never on enum/fn/alias","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Attach #[serde_multikey] directly above the struct declaration","Double-check the item kind after refactors that move code around","Remember proc-macro attributes cannot be used on enums or aliases"],"tags":["rust","proc-macro","compile-time"],"backgroundTag":"invalid-argument-value","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}