reflex-dev/reflex · error · TypeError

`rx.EventHandler` parameters are only supported on component

Error message

`rx.EventHandler` parameters are only supported on component-returning memos. Got `{parameter.name}` in `{fn_name}`.

What it means

An `@rx.memo` function declared a parameter annotated `rx.EventHandler`, but event handler props only make sense for memos that return components (they become callable event triggers on the compiled component). A Var-returning memo compiles to a pure expression with no component to attach the trigger to, so Reflex rejects it at decoration time.

Source

Thrown at packages/reflex-base/src/reflex_base/components/memo.py:955


def _validate_rest(
    parameter: inspect.Parameter, fn_name: str, for_component: bool
) -> None:
    if parameter.name == "children":
        msg = f"`children` in `{fn_name}` cannot be `rx.RestProp`."
        raise TypeError(msg)


def _validate_event_trigger(
    parameter: inspect.Parameter, fn_name: str, for_component: bool
) -> None:
    if not for_component:
        msg = (
            f"`rx.EventHandler` parameters are only supported on component-"
            f"returning memos. Got `{parameter.name}` in `{fn_name}`."
        )
        raise TypeError(msg)
    if parameter.name == "children":
        msg = (
            f"`children` in `{fn_name}` cannot be an `rx.EventHandler`; "
            "use `rx.Var[rx.Component]`."
        )
        raise TypeError(msg)
    if parameter.default is not inspect.Parameter.empty:
        msg = (
            f"`rx.EventHandler` parameter `{parameter.name}` in `{fn_name}` "
            "must not have a default value."
        )
        raise TypeError(msg)


def _placeholder_name_value(name: str, js_prop_name: str, for_component: bool) -> str:
    return js_prop_name + CAMEL_CASE_MEMO_MARKER if for_component else name

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Change the memo to return `rx.Component` if the event handler is required
  2. Remove the `rx.EventHandler` parameter from the Var-returning memo and handle the event in the calling component/state instead
  3. Split into two memos: a Var-returning one for the value and a component-returning one that accepts the event handler

Example fix

// before
@rx.memo
def total(n: rx.Var[int], on_change: rx.EventHandler) -> rx.Var[int]:
    return n * 2

// after
@rx.memo
def total(n: rx.Var[int]) -> rx.Var[int]:
    return n * 2

# handle on_change in the parent component/state
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect, typing, reflex as rx

def check_handlers_only_on_components(fn) -> None:
    hints = typing.get_type_hints(fn)
    ret = hints.get("return")
    is_component = rx.Component in typing.get_args(ret or ())
    for p in inspect.signature(fn).parameters.values():
        if p.annotation is rx.EventHandler and not is_component:
            raise TypeError("remove rx.EventHandler params from Var-returning memos")

Type guard

import typing, reflex as rx

def memo_supports_event_handlers(fn) -> bool:
    ret = typing.get_type_hints(fn).get("return")
    return rx.Component in typing.get_args(ret or ())

Prevention

When it happens

Trigger: Decorating a function whose return annotation is not `rx.Component` (a Var-returning memo) that has a parameter annotated `rx.EventHandler`, e.g. `@rx.memo def total(n: rx.Var[int], on_change: rx.EventHandler) -> rx.Var[int]`. `_validate_event_trigger` runs with `for_component=False` and raises.

Common situations: Migrating a component wrapper into a value-computing memo but leaving the `on_change`/`on_click` handler parameter in place; mixing rendering callbacks into pure computed-value helpers.

Related errors


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