actix/actix-web · error · syn::Error
`MultipartForm` can only be derived for a struct with named…
Error message
`MultipartForm` can only be derived for a struct with named fields
What it means
This is a compile-time error from the `#[derive(MultipartForm)]` proc macro. The derive only accepts structs with named fields because it needs field identifiers to generate per-field handling code (limits, state extraction, etc.). Tuple structs (`struct Foo(String)`) and unit structs (`struct Foo;`) are rejected because the macro cannot map multipart field names to unnamed positions.
Solutions
- Change the struct to use named fields: `struct Upload { file: Bytes }` instead of `struct Upload(Bytes);`
- If you need a single-field wrapper, still give it a name: `struct Upload { data: Bytes }`
- Remove `#[derive(MultipartForm)]` if the type is not actually used as a multipart form extractor
Example fix
// before
#[derive(MultipartForm)]
struct Upload(Bytes);
// after
#[derive(MultipartForm)]
struct Upload {
data: Bytes,
} Defensive patterns
Strategy: type-guard
Type guard
// No runtime guard needed; this is a compile-time error.
// Ensure the struct uses named fields:
// pub struct MyForm {
// field1: Bytes,
// field2: String,
// }
// Verify with: cargo check Prevention
- Always use named fields on structs annotated with #[derive(MultipartForm)]
- Run cargo check early after adding the derive to catch structural mismatches
- Review the actix-multipart form documentation for the expected struct shape
When it happens
Trigger: Annotating a tuple struct (e.g., `#[derive(MultipartForm)] struct Upload(Bytes);`) or a unit struct (`struct Empty;`) with `#[derive(MultipartForm)]`. The macro matches `data_struct.fields` against `syn::Fields::Named` at line 73-81 and returns this error for `Unnamed` or `Unit`.
Common situations: Developers new to actix-multipart who try to derive on a tuple struct, or who copy a serde pattern using unnamed fields. Refactoring a named-field struct into a tuple struct without removing the derive.
Related errors
- Could not parse size limit
- Multiple fields named
- argument to scope macro is not a string literal, expected…
- invalid service definition, expected #
- missing arguments for scope macro, expected…
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/73b0dcfae6a23a9c.
Report an issue: GitHub.
Appendix: source
Thrown at actix-multipart-derive/src/lib.rs:76
pub fn impl_multipart_form(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input: syn::DeriveInput = parse_macro_input!(input);
let name = &input.ident;
let data_struct = match &input.data {
syn::Data::Struct(data_struct) => data_struct,
_ => {
return compile_err(syn::Error::new(
input.ident.span(),
"`MultipartForm` can only be derived for structs",
))
}
};
let fields = match &data_struct.fields {
syn::Fields::Named(fields_named) => fields_named,
_ => {
return compile_err(syn::Error::new(
input.ident.span(),
"`MultipartForm` can only be derived for a struct with named fields",
))
}
};
let attrs = match MultipartFormAttrs::from_derive_input(&input) {
Ok(attrs) => attrs,
Err(err) => return err.write_errors().into(),
};
// Parse the field attributes
let parsed = match fields
.named
.iter()
.map(|field| {
let rust_name = field.ident.as_ref().unwrap();
let attrs = FieldAttrs::from_field(field).map_err(|err| err.write_errors())?;View on GitHub (pinned to 4d435abc28)