seanmonstar/warp · error

Multipart field is missing a name

Error message

Multipart field is missing a name

What it means

warp's multipart filter returns a MultipartFieldMissingName error when a received multipart part has neither a name nor a file name in its Content-Disposition. Named parts are the API contract for part.part.name(); anonymous parts cannot be addressed.

Solutions

  1. Fix the client/test to always send name="..." in each part's Content-Disposition
  2. Generate multipart bodies with a proper library (e.g. multer, reqwest multipart) instead of manual strings
  3. If anonymous parts are expected, handle the error from the stream instead of unwrapping Ok

Example fix

// before
let body = "--B\r\nContent-Type: text/plain\r\n\r\nhi\r\n--B--";
// after
let body = "--B\r\nContent-Disposition: form-data; name=\"field\"\r\n\r\nhi\r\n--B--";
Defensive patterns

Strategy: validation

Validate before calling

// ensure every generated part includes a name attribute
assert!(body.contains("Content-Disposition: form-data; name="), "multipart part missing name");

Try / catch

// warp errors are Rejects: filter and map them
let parts = req multipart stream
    .try_filter_map(|part| async move {
        if part.name().is_some() { Ok(Some(part)) } else { Ok(None) }
    });
// or at the route: .map(|result| result.map_err(|re| ...))

Prevention

When it happens

Trigger: A client POSTs multipart/form-data where a part's Content-Disposition lacks both 'name=' and 'filename=' attributes; warp::multipart's Stream then yields this error on poll_next.

Common situations: Hand-rolled multipart bodies in tests or curl scripts missing the name attribute; misbehaving HTTP clients or proxies stripping Content-Disposition parameters.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of seanmonstar/warp@ff34d7213e (2026-09-09). Data as JSON: /api/errors/f184d3392a61d5a1. Report an issue: GitHub.

Appendix: source

Thrown at src/filters/multipart.rs:127

// ===== impl FormData =====

impl fmt::Debug for FormData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FormData").finish()
    }
}

impl Stream for FormData {
    type Item = Result<Part, crate::Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        match self.inner.poll_next_field(cx) {
            Poll::Pending => Poll::Pending,
            Poll::Ready(Ok(Some(part))) => {
                if part.name().is_some() || part.file_name().is_some() {
                    Poll::Ready(Some(Ok(Part { part })))
                } else {
                    Poll::Ready(Some(Err(crate::Error::new(MultipartFieldMissingName))))
                }
            }
            Poll::Ready(Ok(None)) => Poll::Ready(None),
            Poll::Ready(Err(err)) => Poll::Ready(Some(Err(crate::Error::new(err)))),
        }
    }
}

// ===== impl Part =====

impl Part {
    /// Get the name of this part.
    pub fn name(&self) -> &str {
        self.part
            .name()
            .unwrap_or_else(|| self.part.file_name().expect("checked for name previously"))
    }

View on GitHub (pinned to ff34d7213e)