{"record":{"id":"3690a299ad529506","repo":"actix/actix-web","slug":"multipartform-can-only-be-derived-for-structs","errorCode":null,"errorMessage":"`MultipartForm` can only be derived for structs","messagePattern":"`MultipartForm` can only be derived for structs","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"critical","filePath":"actix-multipart-derive/src/lib.rs","lineNumber":66,"sourceCode":"    ty: &'t Type,\n}\n\n/// Implements `MultipartCollect` for a struct so that it can be used with the `MultipartForm`\n/// extractor.\n///\n/// See [`actix_multipart::form::MultipartForm`] for supported fields and attributes.\n///\n/// [`actix_multipart::form::MultipartForm`]: https://docs.rs/actix-multipart/latest/actix_multipart/form/struct.MultipartForm.html\n#[proc_macro_derive(MultipartForm, attributes(multipart))]\npub fn impl_multipart_form(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let input: syn::DeriveInput = parse_macro_input!(input);\n\n    let name = &input.ident;\n\n    let data_struct = match &input.data {\n        syn::Data::Struct(data_struct) => data_struct,\n        _ => {\n            return compile_err(syn::Error::new(\n                input.ident.span(),\n                \"`MultipartForm` can only be derived for structs\",\n            ))\n        }\n    };\n\n    let fields = match &data_struct.fields {\n        syn::Fields::Named(fields_named) => fields_named,\n        _ => {\n            return compile_err(syn::Error::new(\n                input.ident.span(),\n                \"`MultipartForm` can only be derived for a struct with named fields\",\n            ))\n        }\n    };\n\n    let attrs = match MultipartFormAttrs::from_derive_input(&input) {\n        Ok(attrs) => attrs,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/actix/actix-web/blob/4d435abc281842f3cbee165b6cde739e001d3a25/actix-multipart-derive/src/lib.rs#L48-L84","documentation":"A compile-time syn::Error emitted by the MultipartForm derive macro (multipart-derive/src/lib.rs:66) when #[derive(MultipartForm)] is applied to anything other than a struct - i.e. an enum or union. The macro matches input.data against syn::Data::Struct (lib.rs:63) and, on mismatch, returns this error via compile_err. There is a separate, similar message for structs without named fields (lib.rs:76).","triggerScenarios":"Annotating an enum or union with #[derive(MultipartForm)]: e.g. `#[derive(MultipartForm)] enum E { ... }`. The build fails with this message pointing at the type's span.","commonSituations":"Trying to model a discriminated form payload as an enum; copy-pasting the derive onto the wrong item; misunderstanding that the macro only supports plain structs with named fields.","solutions":["Define a struct with named fields and derive MultipartForm on it.","If you need variants, wrap the struct in an enum manually and extract MultipartForm on the inner struct.","Ensure all fields are named (not tuple/struct-unit); the macro requires syn::Fields::Named (lib.rs:74)."],"exampleFix":"// before\n#[derive(MultipartForm)]\nenum Shape { A(Text<String>), B(TempFile) } // compile error\n\n// after\n#[derive(MultipartForm)]\nstruct Form { label: Text<String>, file: Option<TempFile> }","handlingStrategy":"type-guard","validationCode":"// The macro only accepts structs with named fields; check before annotating\n","typeGuard":"// Only derive on structs (named fields); never on enums/unions\n#[derive(MultipartForm)]\nstruct Upload {\n    name: Text<String>,\n    file: TempFile,\n}\n// enum E { ... } // do NOT put #[derive(MultipartForm)] here","tryCatchPattern":null,"preventionTips":["Derive MultipartForm only on structs with named fields.","For polymorphism, keep the form a struct and branch in handler logic.","Read the macro docs: tuple/unit structs and enums are unsupported."],"tags":["multipart","derive-macro","actix-multipart","compile-error"],"backgroundTag":null,"analyzedSha":"4d435abc281842f3cbee165b6cde739e001d3a25","analyzedAt":"2026-08-09T01:01:40.926Z","contentChangedAt":"2026-08-09T01:01:40.926Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}