reflex-dev/reflex · error · TypeError

All parameters of `{fn_name}` must be annotated as `rx.Var[.

Error message

All parameters of `{fn_name}` must be annotated as `rx.Var[...]` or `rx.RestProp`, got `{annotation}` for `{param_name}`.

What it means

Every parameter of an `@rx.memo` function must be annotated with `rx.Var[...]` (or be an `rx.RestProp` / children parameter). `_classify_parameter` walks the classification order and, finding no match for the annotation, raises this TypeError telling you exactly which parameter and annotation failed.

Source

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

        annotation: The parameter annotation.
        param_name: The parameter name (some kinds care, e.g. ``children``).
        fn_name: The function name for error messages.

    Returns:
        The matched ``(kind, kind_data)``.

    Raises:
        TypeError: If no kind matches.
    """
    for kind in _CLASSIFICATION_ORDER:
        matched, kind_data = _SPECS[kind].classify(annotation, param_name)
        if matched:
            return kind, kind_data
    msg = (
        f"All parameters of `{fn_name}` must be annotated as `rx.Var[...]` "
        f"or `rx.RestProp`, got `{annotation}` for `{param_name}`."
    )
    raise TypeError(msg)


def _build_args_function(
    params: tuple[MemoParam, ...], return_expr: Var
) -> ArgsFunctionOperation:
    """Build the JS ``ArgsFunctionOperation`` that wraps a memo's return expression.

    Args:
        params: The memo parameters.
        return_expr: The return expression of the memo body.

    Returns:
        The compiled function operation.
    """
    rest_param = _get_rest_param(params)
    if _get_children_param(params) is None and rest_param is None:
        return ArgsFunctionOperation.create(
            args_names=tuple(param.placeholder_name for param in params),

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Annotate every parameter as `rx.Var[...]`, e.g. `label: rx.Var[str]`.
  2. For prop spreads, annotate the parameter as `rx.RestProp`.
  3. For children, use the supported children parameter convention instead of a custom annotation.
  4. Run a quick `inspect.signature` check or rely on the error message, which names the offending parameter.

Example fix

# before
@rx.memo
def badge(label):
    return rx.text(label)

# after
@rx.memo
def badge(label: rx.Var[str]):
    return rx.text(label)
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect, typing

def has_var_annotations(fn) -> bool:
    hints = typing.get_type_hints(fn)
    return all(p.name in hints for p in inspect.signature(fn).parameters.values())

Type guard

import typing, reflex as rx

def is_valid_memo_annotation(annotation) -> bool:
    # rx.Var[...] origins and rx.RestProp are accepted by _classify_parameter
    if annotation is rx.RestProp or type(annotation) is type(rx.RestProp):
        return True
    origin = typing.get_origin(annotation)
    return origin is not None and origin in (rx.Var, rx.Var.__class_getitem__.__self__ if hasattr(rx.Var, "__class_getitem__") else rx.Var)

Try / catch

try:
    @rx.memo
    def item(label: rx.Var[str]): ...
except TypeError as e:
    # message names the offending param; fix the annotation and re-apply
    raise

Prevention

When it happens

Trigger: Decorating a function with `@rx.memo` where a parameter is unannotated or annotated with a plain type like `def badge(label: str): ...` or `def row(item): ...`. Raised at decoration time.

Common situations: Converting a regular render function to `@rx.memo` without adding annotations; annotating with Python types (`int`, `str`, a dataclass) instead of `rx.Var[int]`; IDE auto-removing 'unused' annotations; partial refactor where one param was missed.

Related errors


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