actix/actix-web · error · actix_multipart::Error

Duplicate field found

Error message

Duplicate field found: {_0}

What it means

Error::DuplicateField(String) is raised by the MultipartForm extractor (form/mod.rs:90 and :169) when a second part with the same field name arrives on a struct field configured with #[multipart(duplicate_field = "deny")] and the field type is not a Vec. The derive macro wires the Deny policy into handle_field; on collision it returns this error which becomes a 400 Bad Request (error.rs:103). Vec fields ignore the policy and always accumulate.

Solutions

  1. If duplicates are legitimate, change the field type to Vec<T> (which always allows repeats) or Option<Vec<T>>.
  2. Switch the policy to ignore (default, keeps first) or replace (keeps last) via #[multipart(duplicate_field = "ignore")] / "replace".
  3. If duplicates should be rejected, keep deny and fix the client to send the field only once.

Example fix

// before
#[derive(MultipartForm)]
#[multipart(duplicate_field = "deny")]
struct Form { email: Text<String> } // 2x "email" => 400

// after (allow multiple)
#[derive(MultipartForm)]
struct Form { emails: Vec<Text<String>> }
Defensive patterns

Strategy: validation

Validate before calling

// Declare field multiplicity to match client behaviour
// duplicates expected -> use Vec; otherwise set an explicit policy

Type guard

// Choose field type by expected cardinality
struct Form {
    // single, no dups allowed:
    email: Text<String>,
    // multiple allowed:
    tags: Vec<Text<String>>,
}

Try / catch

match form_result {
    Err(actix_web::Error e) if is_duplicate_field(&e) => {
        return HttpResponse::BadRequest().body("field sent more than once");
    }
    _ => { /* ... */ }
}

Prevention

When it happens

Trigger: A client POSTs multipart/form-data containing two parts named identically (e.g. two "email" fields) to a handler whose struct uses #[multipart(duplicate_field = "deny")] with a non-Vec field. See test_duplicate_field at form/mod.rs:800.

Common situations: Browser forms with duplicate input names; a frontend bug re-sending a field; testing duplicate submission; changing a field from single to multi-value without updating the struct.

Related errors


AI-assisted analysis of actix/actix-web@7ae209e4a4 (2026-08-09). Data as JSON: /api/errors/a7111b5aeb4fe0d6. Report an issue: GitHub.

Appendix: source

Thrown at actix-multipart/src/error.rs:86

    /// HTTP payload error.
    #[display("Payload error: {_0}")]
    Payload(PayloadError),

    /// Stream is not consumed.
    #[display("Stream is not consumed")]
    NotConsumed,

    /// Form field handler raised error.
    #[display("An error occurred processing field '{name}': {source}")]
    Field {
        name: String,
        source: actix_web::Error,
    },

    /// Duplicate field found (for structure that opted-in to denying duplicate fields).
    #[display("Duplicate field found: {_0}")]
    #[from(ignore)]
    DuplicateField(#[error(not(source))] String),

    /// Required field is missing.
    #[display("Required field is missing: {_0}")]
    #[from(ignore)]
    MissingField(#[error(not(source))] String),

    /// Unknown field (for structure that opted-in to denying unknown fields).
    #[display("Unknown field: {_0}")]
    #[from(ignore)]
    UnknownField(#[error(not(source))] String),
}

/// Return `BadRequest` for `MultipartError`.
impl ResponseError for Error {
    fn status_code(&self) -> StatusCode {
        match &self {
            Error::Field { source, .. } => source.as_response_error().status_code(),
            Error::ContentTypeIncompatible => StatusCode::UNSUPPORTED_MEDIA_TYPE,

View on GitHub (pinned to 7ae209e4a4)