{"record":{"id":"2042c3f8dc39eafa","repo":"reflex-dev/reflex","slug":"all-parameters-of-fn-name-must-be-annotate","errorCode":null,"errorMessage":"All parameters of `{fn.__name__}` must be annotated as `rx.Var[...]` or `rx.RestProp`. Missing annotation for `{parameter.name}`.","messagePattern":"All parameters of `(.+?)` must be annotated as `rx\\.Var\\[\\.\\.\\.\\]` or `rx\\.RestProp`\\. Missing annotation for `(.+?)`\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/reflex-base/src/reflex_base/components/memo.py","lineNumber":1291,"sourceCode":"        annotation = hints.get(parameter.name, parameter.annotation)\n        if _GET_TYPE_HINTS_WRAPS_NONE_DEFAULT and parameter.default is None:\n            annotation = _strip_optional(annotation)\n        is_missing = annotation is inspect.Parameter.empty\n        # Legacy `@rx.memo` (the old `custom_component`) accepted missing and\n        # bare Python-type annotations and auto-wrapped them in a `Var`. Coerce\n        # both into `rx.Var[...]` and flag the parameter, so one deprecation\n        # warning points the user at the params that still need an explicit\n        # annotation. Strict callers (`defaulted_params is None`) reject a\n        # missing annotation here; a bare type falls through to\n        # `_classify_parameter`, which rejects it.\n        is_legacy = defaulted_params is not None and not _is_memo_annotation(annotation)\n        if is_missing or is_legacy:\n            if defaulted_params is None:\n                msg = (\n                    f\"All parameters of `{fn.__name__}` must be annotated as `rx.Var[...]` \"\n                    f\"or `rx.RestProp`. Missing annotation for `{parameter.name}`.\"\n                )\n                raise TypeError(msg)\n            if parameter.name == \"children\":\n                annotation = Var[Component]\n            elif is_missing:\n                annotation = Var[Any]\n            else:\n                annotation = Var[annotation]\n            defaulted_params.append(parameter.name)\n            if is_missing and missing_params is not None:\n                missing_params.append(parameter.name)\n\n        # Children parameters by name must match the children kind exactly —\n        # otherwise we accept a value-typed `children` and emit confusing JSX.\n        if (\n            parameter.name == \"children\"\n            and not _children_annotation_is_valid(annotation)\n            and not _is_event_handler_annotation(annotation)[0]\n        ):\n            msg = (","sourceCodeStart":1273,"sourceCodeEnd":1309,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/packages/reflex-base/src/reflex_base/components/memo.py#L1273-L1309","documentation":"Every parameter of an `@rx.memo` function must be annotated as `rx.Var[...]` (or `rx.RestProp`/`rx.EventHandler` for those kinds). This error fires when a parameter has no annotation at all, or has a 'legacy' bare annotation (e.g. `int` instead of `rx.Var[int]`), and strict-mode inference is disabled (`defaulted_params is None`). Reflex raises it at decoration time via `_analyze_params`.","triggerScenarios":"Writing `@rx.memo def label(text) -> ...` (missing annotation) or `@rx.memo def label(text: str) -> ...` (bare type) in strict mode — `_analyze_params` finds `is_missing or is_legacy` with `defaulted_params is None` and raises.","commonSituations":"Porting a plain helper function into `@rx.memo` without adding Var annotations; relying on legacy bare-type annotations that older Reflex versions auto-wrapped; partial annotations after a refactor.","solutions":["Annotate every parameter with `rx.Var[...]` (e.g. `text: rx.Var[str]`)","Use `rx.RestProp` for rest props or `rx.EventHandler` for event triggers as appropriate","Enable legacy/default-inference mode if you must keep bare annotations (not recommended for new code)"],"exampleFix":"# before\n@rx.memo\ndef greeting(name) -> rx.Var[str]:\n    return \"Hello \" + name\n\n# after\n@rx.memo\ndef greeting(name: rx.Var[str]) -> rx.Var[str]:\n    return \"Hello \" + name","handlingStrategy":"type-guard","validationCode":"import inspect, typing, reflex as rx\n\ndef all_params_annotated_as_var(fn) -> None:\n    hints = typing.get_type_hints(fn)\n    for name, p in inspect.signature(fn).parameters.items():\n        if p.kind is inspect.Parameter.VAR_POSITIONAL:\n            continue\n        ann = hints.get(name)\n        if ann is None or (typing.get_origin(ann) is not rx.Var and ann not in (rx.RestProp, rx.EventHandler)):\n            raise TypeError(f\"param {name!r} needs an rx.Var[...] annotation\")","typeGuard":"import typing, reflex as rx\n\ndef memo_params_well_annotated(fn) -> bool:\n    hints = typing.get_type_hints(fn)\n    return all(\n        typing.get_origin(ann) is rx.Var or ann in (rx.RestProp, rx.EventHandler)\n        for ann in hints.values() if ann is not None\n    ) and len(hints) >= len(inspect.signature(fn).parameters)","tryCatchPattern":null,"preventionTips":["Always annotate memo parameters as rx.Var[...] — strict mode rejects bare types","Enable strict linting (mypy/pyright) with disallow-untyped-defs for modules containing memos","Import memo modules in tests so signature errors surface at test time, not at runtime"],"tags":["reflex","rx-memo","typeerror","type-annotations","strict-mode"],"backgroundTag":"missing-type-annotation","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}