reflex-dev/reflex · error · EventHandlerTypeError

Event handler argument conflicts with a reserved upload…

Error message

Event handler {self.fn.__name__} argument {clash!r} conflicts with a reserved upload argument.

What it means

When an upload event spec is combined with extra bound arguments, the client upload handler forwards reserved argument names (the upload kwargs). A user argument sharing one of those names would silently clobber the upload payload, so it is rejected.

Solutions

  1. Rename the colliding argument (and the handler parameter) to something unique like my_files or payload_files
  2. Pass the value through state instead of as a bound event argument

Example fix

# before
State.upload(rx.upload_files(State.h), files=selected_files)
# after
State.upload(rx.upload_files(State.h), my_files=selected_files)
Defensive patterns

Strategy: validation

Validate before calling

# Avoid mixing upload specs with kwargs named like upload internals
upload_call_args = {'files', 'file'}
assert not (set(kwargs) & upload_call_args) or 'rename kwargs before calling with an upload spec'

Prevention

When it happens

Trigger: Calling a handler that mixes rx.upload_files(...) with keyword arguments whose names collide with the reserved upload argument names used internally (e.g. files, upload_id-like reserved keys).

Common situations: Handlers that accept a parameter commonly named like upload internals (files, url, data) and also receive an upload spec plus that kwarg in the same call.

Related errors


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

Appendix: source

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

            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}
            clash = next((name for name in payload_names if name in reserved), None)
            if clash is not None:
                msg = (
                    f"Event handler {self.fn.__name__} argument {clash!r} conflicts "
                    "with a reserved upload argument."
                )
                raise EventHandlerTypeError(msg)
            # The client uploadFiles handler forwards exactly the args named here,
            # so it never has to know the reserved upload keys.
            return upload_event_spec.with_args((
                *upload_event_spec.args,
                *payload,
                (
                    Var(_js_expr=UPLOAD_EVENT_ARG_NAMES_KEY),
                    LiteralVar.create(payload_names),
                ),
            ))

        # Return the event spec.
        return EventSpec(
            handler=self, args=tuple(payload), event_actions=self.event_actions.copy()
        )


@dataclasses.dataclass(

View on GitHub (pinned to 45b8ed5ab7)