reflex-dev/reflex · error · MissingAnnotationError
MissingAnnotationError
Error message
MissingAnnotationError
What it means
Args specs for event triggers map incoming event arguments to names; when resolving annotations, a non-lambda callable's parameter has no annotation available, so the framework cannot type the event arg and raises MissingAnnotationError.
Source
Thrown at packages/reflex-base/src/reflex_base/event/__init__.py:2164
def resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):
"""Resolve the annotation for the given argument name.
Args:
annotations: The annotations.
arg_name: The argument name.
spec: The specs which the annotations come from.
Returns:
The resolved annotation.
Raises:
MissingAnnotationError: If the annotation is missing for non-lambda methods.
"""
annotation = annotations.get(arg_name)
if annotation is None:
if not isinstance(spec, types.LambdaType):
raise MissingAnnotationError(var_name=arg_name)
return dict[str, dict]
return annotation
@lru_cache
def parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):
"""Parse the args provided in the ArgsSpec of an event trigger.
Args:
arg_spec: The spec of the args.
Returns:
The parsed args.
"""
# if there's multiple, the first is the default
if isinstance(arg_spec, Sequence):
annotations = [get_type_hints(one_arg_spec) for one_arg_spec in arg_spec]
arg_spec = arg_spec[0]View on GitHub (pinned to 45b8ed5ab7)
Solutions
- Annotate all parameters of the function: def handle(e: rx.event.MouseEvent): ...
- Convert the function to a lambda if the arg types can be inferred from context
- Prefer decorated state event handlers (@rx.event) which enforce annotations
Example fix
# before
def do_thing(value):
...
rx.button('Go', on_click=lambda e: do_thing(e.value))
# after
def do_thing(value: str):
...
rx.button('Go', on_click=lambda e: do_thing(e.value)) Defensive patterns
Strategy: type-guard
Validate before calling
import typing, types
def fully_annotated(fn) -> bool:
hints = typing.get_type_hints(fn)
params = [p for p in typing.get_type_hints(fn, include_extras=False)]
return all(p in hints for p in inspect.signature(fn).parameters) Type guard
def has_all_annotations(fn) -> TypeGuard[Callable]: import inspect, typing; return all(p.annotation is not inspect.Parameter.empty for p in inspect.signature(fn).parameters.values())
Try / catch
try:
rx.el.button('x', on_click=my_func)
except MissingAnnotationError:
# add annotations to my_func params, or wrap in a lambda Prevention
- Annotate every parameter of any function used as an event trigger
- Prefer @rx.event state handlers and lambdas for triggers
When it happens
Trigger: Passing a plain function (not a lambda) as an event trigger or arg spec whose parameters lack type annotations, e.g. on_click=plain_func where def plain_func(e): ... has no annotation for e.
Common situations: Using module-level utility functions instead of state handlers/lambdas; refactoring lambdas into named functions and dropping annotations.
Related errors
- `{handler_name}` handler should have a parameter annotated a
- `rx.EventHandler` parameters are only supported on component
- `children` in `{fn_name}` cannot be an `rx.EventHandler`; us
- `rx.EventHandler` parameter `{parameter.name}` in `{fn_name}
- `@rx.memo` on `{fn.__name__}` must return `rx.Component` or
AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28).
Data as JSON: /api/errors/5dc9fcd1787bf9eb.
Report an issue: GitHub.