{"id":"cb5a95496b767b90","repo":"actix/actix-web","slug":"multiple-fields-named","errorCode":null,"errorMessage":"Multiple fields named: `{}`","messagePattern":"Multiple fields named: `(.+?)`","errorType":"exception","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"actix-multipart-derive/src/lib.rs","lineNumber":125,"sourceCode":"\n            Ok(ParsedField {\n                serialization_name,\n                rust_name,\n                limit,\n                ty: &field.ty,\n            })\n        })\n        .collect::<Result<Vec<_>, TokenStream>>()\n    {\n        Ok(attrs) => attrs,\n        Err(err) => return err,\n    };\n\n    // Check that field names are unique\n    let mut set = HashSet::new();\n    for field in &parsed {\n        if !set.insert(field.serialization_name.clone()) {\n            return compile_err(syn::Error::new(\n                field.rust_name.span(),\n                format!(\"Multiple fields named: `{}`\", field.serialization_name),\n            ));\n        }\n    }\n\n    // Return value when a field name is not supported by the form\n    let unknown_field_result = if attrs.deny_unknown_fields {\n        quote!(::std::result::Result::Err(\n            ::actix_multipart::MultipartError::UnknownField(field.name().unwrap().to_string())\n        ))\n    } else {\n        quote!(::actix_multipart::form::discard_field(field, limits).await)\n    };\n\n    // Value for duplicate action\n    let duplicate_field = match attrs.duplicate_field {\n        DuplicateField::Ignore => quote!(::actix_multipart::form::DuplicateField::Ignore),","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/actix/actix-web/blob/937960ca67f20e14ffe2a075bf6d4593502be12c/actix-multipart-derive/src/lib.rs#L107-L143","documentation":"After resolving each field's serialization name (either the Rust name or a `#[multipart(rename = \"...\")]` value), the macro builds a `HashSet` and rejects duplicates at actix-multipart-derive/src/lib.rs:122-129. Two fields mapping to the same incoming form name would make parsing ambiguous, so the macro aborts.","triggerScenarios":"Two fields renamed to the same string, e.g. `#[multipart(rename = \"file\")]` on two fields; or a `rename` that collides with another field's default name.","commonSituations":"Renaming fields to match a legacy/external form field name and accidentally clashing with an existing field, or copy-pasting a rename attribute between fields.","solutions":["Give each field a unique serialization name by adjusting or removing the conflicting `rename`.","If two fields genuinely share one incoming part, merge them into a single field of a composite type.","Set `#[multipart(duplicate_field = \"deny|ignore|replace\")]` only if you intend runtime duplicate handling — this does not bypass the compile-time name-uniqueness check."],"exampleFix":"// before\n#[derive(MultipartForm)]\nstruct Form {\n    #[multipart(rename = \"file\"))]\n    a: Field,\n    #[multipart(rename = \"file\"))]\n    b: Field,\n}\n\n// after\n#[derive(MultipartForm)]\nstruct Form {\n    #[multipart(rename = \"file_a\"))]\n    a: Field,\n    #[multipart(rename = \"file_b\"))]\n    b: Field,\n}","handlingStrategy":"validation","validationCode":"// Collect all serialization names (rust name or #[multipart(rename)]) into a set\n// and assert uniqueness before relying on the derive.\nfn assert_unique_names(names: &[&str]) {\n    let mut seen = std::collections::HashSet::new();\n    for n in names {\n        assert!(seen.insert(*n), \"duplicate field name: {}\", n);\n    }\n}\n// assert_unique_names(&[\"file_a\", \"file_b\", \"file_a\"]); // panics in your test","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Audit `rename` attributes whenever you add a new field.","Keep a single naming convention (either all renamed or none) to avoid accidental collisions."],"tags":["rust","actix","actix-multipart","macro","compile-time","validation"],"analyzedSha":"937960ca67f20e14ffe2a075bf6d4593502be12c","analyzedAt":"2026-08-06T01:15:46.978Z","schemaVersion":2}