aio-libs/aiohttp · error · ValueError

Multipart field missing name.

Error message

Multipart field missing name.

What it means

While parsing multipart/form-data in BaseRequest.post(), each BodyPartReader field must carry a name (from Content-Disposition: name=). If field.name is None the part is anonymous and aiohttp raises ValueError('Multipart field missing name.'), since form fields are keyed by name.

Solutions

  1. Catch ValueError in the handler around await request.post() and return 400.
  2. Validate Content-Disposition before parsing multipart.
  3. Use request.multipart() directly to inspect anonymous parts yourself.

Example fix

try:
    data = await request.post()
except ValueError:
    raise web.HTTPBadRequest(text='malformed multipart: missing field name')
Defensive patterns

Strategy: try-catch

Validate before calling

reader = await request.multipart()
async for part in reader:
    if getattr(part, 'name', None) is None:
        raise web.HTTPBadRequest(text='multipart field missing name')

Try / catch

try:
    data = await request.post()
except ValueError:
    raise web.HTTPBadRequest(text='malformed multipart payload')

Prevention

When it happens

Trigger: A multipart part whose Content-Disposition header omits the name parameter; a file part with only filename= and no name=.

Common situations: Malformed clients; custom multipart builders omitting name; buggy HTTP libraries generating parts without Content-Disposition name.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/1eeaeb25f28acf00. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/web_request.py:749

            "application/x-www-form-urlencoded",
            "multipart/form-data",
        ):
            self._post = MultiDictProxy(MultiDict())
            return self._post

        out: MultiDict[str | bytes | FileField] = MultiDict()

        if content_type == "multipart/form-data":
            multipart = await self.multipart()
            max_size = self._client_max_size

            size = 0
            while (field := await multipart.next()) is not None:
                field_ct = field.headers.get(hdrs.CONTENT_TYPE)

                if isinstance(field, BodyPartReader):
                    if field.name is None:
                        raise ValueError("Multipart field missing name.")

                    # Note that according to RFC 7578, the Content-Type header
                    # is optional, even for files, so we can't assume it's
                    # present.
                    # https://tools.ietf.org/html/rfc7578#section-4.4
                    if field.filename:
                        # store file in temp file
                        tmp = await self._loop.run_in_executor(
                            None, tempfile.TemporaryFile
                        )
                        while chunk := await field.read_chunk(size=DEFAULT_CHUNK_SIZE):
                            async for decoded_chunk in field.decode_iter(chunk):
                                await self._loop.run_in_executor(
                                    None, tmp.write, decoded_chunk
                                )
                                size += len(decoded_chunk)
                                if 0 < max_size < size:
                                    await self._loop.run_in_executor(None, tmp.close)

View on GitHub (pinned to d041d4d0fd)