reflex-dev/reflex · error · EventHandlerTypeError

Event handler {self.fn.__name__} received multiple file uplo

Error message

Event handler {self.fn.__name__} received multiple file upload arguments.

What it means

A single event-handler call may accept only one file-upload construct (rx.upload_files(...) or rx.upload_files_chunk(...)). Passing two means the framework cannot build one coherent upload event spec.

Source

Thrown at packages/reflex-base/src/reflex_base/event/__init__.py:660

            raise EventHandlerTypeError(msg)

        fn_args = fn_args[: len(args)] + list(kwargs)
        event_args = [*args, *kwargs.values()]

        # Construct the payload.
        payload = []
        upload_event_spec = None
        for fn_arg, arg in zip(fn_args, event_args, strict=False):
            # Special case for file uploads. The upload arg takes its own
            # positional slot so the remaining args stay aligned with fn_args,
            # but its parameter name is re-derived server-side in as_event_spec.
            if isinstance(arg, (FileUpload, UploadFilesChunk)):
                if upload_event_spec is not None:
                    msg = (
                        f"Event handler {self.fn.__name__} received multiple file "
                        "upload arguments."
                    )
                    raise EventHandlerTypeError(msg)
                upload_event_spec = arg.as_event_spec(handler=self)
                continue

            # Otherwise, convert to JSON.
            try:
                payload.append((Var(_js_expr=fn_arg), LiteralVar.create(arg)))
            except TypeError as e:
                msg = f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
                raise EventHandlerTypeError(msg) from e

        if upload_event_spec is not None:
            if not payload:
                return upload_event_spec
            # The extra bound args share the flat payload with the synthetic
            # upload args, so reject names that would clobber a reserved upload
            # key (files, upload_id, extra_headers, ...).
            payload_names = [name._js_expr for name, _ in payload]
            reserved = {name._js_expr for name, _ in upload_event_spec.args}

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Split into two separate event-handler calls
  2. Combine both uploads into a single rx.upload_files / rx.upload_files_chunk argument
  3. Drop the stale upload argument left over from migration

Example fix

# before
State.upload(rx.upload_files(State.h1), rx.upload_files_chunk(State.h2))
# after
State.upload(rx.upload_files(State.h1)); State.upload_chunked(rx.upload_files_chunk(State.h2))
Defensive patterns

Strategy: validation

Validate before calling

from reflex_base.event import FileUpload, UploadFilesChunk

def count_upload_args(args):
    return sum(1 for a in args if isinstance(a, (FileUpload, UploadFilesChunk)))
# assert count_upload_args(args) <= 1 before calling

Prevention

When it happens

Trigger: Calling a handler with two arguments that are FileUpload/UploadFilesChunk instances, e.g. State.up(rx.upload_files(State.h1), rx.upload_files_chunk(State.h2)).

Common situations: Trying to upload two different file sets in one event, or accidentally leaving an old rx.upload_files call in when migrating to chunked uploads.

Related errors


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