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

Unknown field

Error message

Unknown field: {_0}

What it means

Error::UnknownField(String) is raised by code generated by the MultipartForm derive macro (multipart-derive/src/lib.rs:135) when a struct is marked #[multipart(deny_unknown_fields)] and an incoming part's name does not match any declared field. Without deny_unknown_fields unknown parts are silently discarded (lib.rs:138). The error surfaces as a 400 Bad Request.

Solutions

  1. Remove #[multipart(deny_unknown_fields)] if extra fields should be ignored (the default).
  2. Align client and server field names, including any #[multipart(rename = "...")] attributes.
  3. Keep deny_unknown_fields and fix the client to send only known fields.

Example fix

// before
#[derive(MultipartForm)]
#[multipart(deny_unknown_fields)]
struct Form { name: Text<String> } // client sends "legacy" => 400

// after (tolerate extras)
#[derive(MultipartForm)]
struct Form { name: Text<String> } // extras discarded
Defensive patterns

Strategy: validation

Validate before calling

// Only opt into strictness when you control the client
#[derive(MultipartForm)]
struct Form { name: Text<String> } // unknown fields discarded by default
// add #[multipart(deny_unknown_fields)] only if extras are truly an error

Try / catch

match form_result {
    Err(e) if is_unknown_field(&e) => {
        return HttpResponse::BadRequest().body("unexpected form field");
    }
    _ => { /* ... */ }
}

Prevention

When it happens

Trigger: A handler struct annotated #[multipart(deny_unknown_fields)] receives a part whose name is not one of its fields. Test test_deny_unknown at form/mod.rs:744 sends an "unknown" part and expects 400.

Common situations: Client sending extra/legacy fields; field renamed server-side but client still sends the old name; a honeypot anti-spam field; stricter validation turned on during a refactor.

Related errors


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

Appendix: source

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

    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,
            _ => StatusCode::BAD_REQUEST,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]

View on GitHub (pinned to 7ae209e4a4)