{"record":{"id":"f7e0ffd0a4ed3e16","repo":"reflex-dev/reflex","slug":"rx-memo-on-fn-name-must-return-rx-comp","errorCode":null,"errorMessage":"`@rx.memo` on `{fn.__name__}` must return `rx.Component` or `rx.Var[...]`, got `{return_annotation}`.","messagePattern":"`@rx\\.memo` on `(.+?)` must return `rx\\.Component` or `rx\\.Var\\[\\.\\.\\.\\]`, got `(.+?)`\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/reflex-base/src/reflex_base/components/memo.py","lineNumber":2058,"sourceCode":"\n    Raises:\n        TypeError: If the return annotation is not supported, or a non-default\n            ``wrapper`` is given for a var-returning memo.\n    \"\"\"\n    hints = get_type_hints(fn, include_extras=True)\n    return_annotation = hints.get(\"return\", inspect.Signature.empty)\n    missing_return = return_annotation is inspect.Signature.empty\n    if missing_return:\n        return_annotation = Component\n        hints[\"return\"] = Component\n\n    is_component = _is_component_annotation(return_annotation)\n    if not is_component and not _is_var_annotation(return_annotation):\n        msg = (\n            f\"`@rx.memo` on `{fn.__name__}` must return `rx.Component` or \"\n            f\"`rx.Var[...]`, got `{return_annotation}`.\"\n        )\n        raise TypeError(msg)\n    if not is_component and wrapper is not DEFAULT_MEMO_WRAPPER:\n        msg = (\n            \"`@rx.memo` only supports `wrapper=` on component-returning memos; \"\n            f\"`{fn.__name__}` returns `rx.Var[...]`, which compiles to a plain \"\n            \"function.\"\n        )\n        raise TypeError(msg)\n\n    defaulted_params: list[str] = []\n    missing_params: list[str] = []\n    params = _analyze_params(\n        fn,\n        for_component=is_component,\n        hints=hints,\n        defaulted_params=defaulted_params,\n        missing_params=missing_params,\n    )\n","sourceCodeStart":2040,"sourceCodeEnd":2076,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/packages/reflex-base/src/reflex_base/components/memo.py#L2040-L2076","documentation":"The `@rx.memo` decorator requires the decorated function's return annotation to be an `rx.Component` (or subclass) or `rx.Var[...]`. Any other annotation (str, int, None, un-annotated return) fails immediately at decoration time.","triggerScenarios":"`@rx.memo` on `def count() -> int:` or on a function with no return annotation that Reflex cannot resolve to a Component/Var type.","commonSituations":"Adding the decorator to a plain helper function by mistake, or annotating with a custom alias Reflex does not recognize as a component type.","solutions":["Annotate the return as `rx.Component` (or a specific component type) or `rx.Var[str]` etc.","If the function is not a render/value function, remove `@rx.memo`"],"exampleFix":"// before\n@rx.memo\ndef label() -> str:\n    return \"hi\"\n\n// after\n@rx.memo\ndef label() -> rx.Var[str]:\n    return \"hi\"","handlingStrategy":"type-guard","validationCode":"import typing, reflex as rx\n\ndef memo_compatible(fn) -> bool:\n    ret = typing.get_type_hints(fn).get(\"return\")\n    if ret is None:\n        return False\n    if isinstance(ret, type) and issubclass(ret, rx.Component):\n        return True\n    origin = typing.get_origin(ret)\n    return origin is not None and origin is rx.Var","typeGuard":"import typing, reflex as rx\n\ndef is_valid_memo_return(fn) -> bool:\n    ret = typing.get_type_hints(fn).get(\"return\")\n    return ret is rx.Component or ret is rx.Var or (\n        typing.get_origin(ret) is rx.Var\n    )","tryCatchPattern":null,"preventionTips":["Always annotate memo return types explicitly as rx.Component or rx.Var[T]","Run pyright — missing annotations are caught statically"],"tags":["reflex","memo","type-annotation","return-type"],"backgroundTag":"invalid-return-annotation","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}