reflex-dev/reflex · error · TypeError

`@rx.memo` only supports `wrapper=` on component-returning m

Error message

`@rx.memo` only supports `wrapper=` on component-returning memos; `{fn.__name__}` returns `rx.Var[...]`, which compiles to a plain function.

What it means

`@rx.memo(wrapper=...)` is only supported for memos that return `rx.Component`. Memos annotated to return `rx.Var[...]` compile to plain functions and cannot take a wrapper component.

Source

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

    missing_return = return_annotation is inspect.Signature.empty
    if missing_return:
        return_annotation = Component
        hints["return"] = Component

    is_component = _is_component_annotation(return_annotation)
    if not is_component and not _is_var_annotation(return_annotation):
        msg = (
            f"`@rx.memo` on `{fn.__name__}` must return `rx.Component` or "
            f"`rx.Var[...]`, got `{return_annotation}`."
        )
        raise TypeError(msg)
    if not is_component and wrapper is not DEFAULT_MEMO_WRAPPER:
        msg = (
            "`@rx.memo` only supports `wrapper=` on component-returning memos; "
            f"`{fn.__name__}` returns `rx.Var[...]`, which compiles to a plain "
            "function."
        )
        raise TypeError(msg)

    defaulted_params: list[str] = []
    missing_params: list[str] = []
    params = _analyze_params(
        fn,
        for_component=is_component,
        hints=hints,
        defaulted_params=defaulted_params,
        missing_params=missing_params,
    )

    source_module = memo_paths.capture_source_module(fn)

    if missing_return or defaulted_params:
        _warn_missing_annotations(fn.__name__, missing_return, defaulted_params)

    # Build the definition with a deferred body: the decorated function runs on
    # first read of ``.component`` / ``.function`` (see ``_LazyBody``), not here,

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Drop the `wrapper=` argument for Var-returning memos
  2. Or change the memo to return a component if you need wrapper behavior

Example fix

// before
@rx.memo(wrapper=rx.fragment)
def total() -> rx.Var[int]: ...

// after
@rx.memo
def total() -> rx.Var[int]: ...
Defensive patterns

Strategy: type-guard

Validate before calling

import typing, reflex as rx

def can_use_wrapper(fn) -> bool:
    ret = typing.get_type_hints(fn).get("return")
    return isinstance(ret, type) and issubclass(ret, rx.Component)

Type guard

def is_component_memo(fn) -> bool:
    import typing, reflex as rx
    ret = typing.get_type_hints(fn).get("return")
    return isinstance(ret, type) and issubclass(ret, rx.Component)

Prevention

When it happens

Trigger: `@rx.memo(wrapper=SomeWrapper)` on `def total() -> rx.Var[int]:` — a value-returning memo with a wrapper argument.

Common situations: Copying a wrapper-using component memo pattern onto a computed-value memo.

Related errors


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