reflex-dev/reflex · error · MultiPartException

Upload event args must be a text field, not a file.

Error message

Upload event args must be a text field, not a file.

What it means

If a part carries the upload-event-args field name but also has a filename (i.e. it is a file part), the parser rejects it: the args channel must be a plain text field. Otherwise the file would be pushed as a phantom upload or corrupt args decoding.

Source

Thrown at packages/reflex-components-core/src/reflex_components_core/core/_upload.py:411

            msg = 'The Content-Disposition header field "name" must be provided.'
            raise MultiPartException(msg) from err

        if b"filename" not in options:
            # Capture the bound-args field; ignore any other non-file field.
            if field_name == UPLOAD_EVENT_ARGS_FIELD:
                if self._seen_upload_chunk:
                    # The handler is dispatched at the first file part, so a late
                    # args field would be silently dropped; reject it loudly.
                    msg = "Upload event args must precede the file parts."
                    raise MultiPartException(msg)
                self._current_part.is_text_field = True
                self._args_buffer = bytearray()
            return
        if field_name == UPLOAD_EVENT_ARGS_FIELD:
            # A file under the args field name would otherwise be pushed as a
            # phantom file upload; reject it instead of silently dropping it.
            msg = "Upload event args must be a text field, not a file."
            raise MultiPartException(msg)
        filename = _sanitize_upload_filename(
            _user_safe_decode(options[b"filename"], self._charset)
        )

        content_type = ""
        for header_name, header_value in self._current_part.item_headers:
            if header_name == b"content-type":
                content_type = _user_safe_decode(header_value, self._charset)
                break

        self._current_part.field_name = field_name
        self._current_part.filename = filename
        self._current_part.content_type = content_type
        self._current_part.offset = 0
        self._current_part.bytes_emitted = 0
        self._current_part.is_upload_chunk = True
        # The args field precedes the files, so by the first file part the bound
        # args are fully parsed and the handler can be dispatched.

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Rename your file form field so it doesn't collide with the reserved args field name (use the conventional 'files')
  2. Send args as a plain text field without a filename attribute
  3. Use the standard Reflex upload client which never sends files under the args name
Defensive patterns

Strategy: validation

Validate before calling

assert all(p.filename is None for p in parts if p.name == ARGS_FIELD)

Prevention

When it happens

Trigger: Content-Disposition: form-data; name="<args-field>"; filename="x.json" — a file uploaded under the reserved args field name.

Common situations: Custom clients naming their file field identically to Reflex's internal args field name; name collisions when the user picks a field name clashing with the reserved one; fuzzing/malformed requests.

Related errors


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/262edd9bd52e60a1. Report an issue: GitHub.