{"record":{"id":"5dc9fcd1787bf9eb","repo":"reflex-dev/reflex","slug":"missingannotationerror","errorCode":null,"errorMessage":"MissingAnnotationError","messagePattern":"MissingAnnotationError","errorType":"exception","errorClass":"MissingAnnotationError","httpStatus":null,"severity":"error","filePath":"packages/reflex-base/src/reflex_base/event/__init__.py","lineNumber":2164,"sourceCode":"\ndef resolve_annotation(annotations: dict[str, Any], arg_name: str, spec: ArgsSpec):\n    \"\"\"Resolve the annotation for the given argument name.\n\n    Args:\n        annotations: The annotations.\n        arg_name: The argument name.\n        spec: The specs which the annotations come from.\n\n    Returns:\n        The resolved annotation.\n\n    Raises:\n        MissingAnnotationError: If the annotation is missing for non-lambda methods.\n    \"\"\"\n    annotation = annotations.get(arg_name)\n    if annotation is None:\n        if not isinstance(spec, types.LambdaType):\n            raise MissingAnnotationError(var_name=arg_name)\n        return dict[str, dict]\n    return annotation\n\n\n@lru_cache\ndef parse_args_spec(arg_spec: ArgsSpec | Sequence[ArgsSpec]):\n    \"\"\"Parse the args provided in the ArgsSpec of an event trigger.\n\n    Args:\n        arg_spec: The spec of the args.\n\n    Returns:\n        The parsed args.\n    \"\"\"\n    # if there's multiple, the first is the default\n    if isinstance(arg_spec, Sequence):\n        annotations = [get_type_hints(one_arg_spec) for one_arg_spec in arg_spec]\n        arg_spec = arg_spec[0]","sourceCodeStart":2146,"sourceCodeEnd":2182,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/packages/reflex-base/src/reflex_base/event/__init__.py#L2146-L2182","documentation":"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.","triggerScenarios":"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.","commonSituations":"Using module-level utility functions instead of state handlers/lambdas; refactoring lambdas into named functions and dropping annotations.","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"],"exampleFix":"# before\ndef do_thing(value):\n    ...\nrx.button('Go', on_click=lambda e: do_thing(e.value))\n# after\ndef do_thing(value: str):\n    ...\nrx.button('Go', on_click=lambda e: do_thing(e.value))","handlingStrategy":"type-guard","validationCode":"import typing, types\n\ndef fully_annotated(fn) -> bool:\n    hints = typing.get_type_hints(fn)\n    params = [p for p in typing.get_type_hints(fn, include_extras=False)]\n    return all(p in hints for p in inspect.signature(fn).parameters)","typeGuard":"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())","tryCatchPattern":"try:\n    rx.el.button('x', on_click=my_func)\nexcept MissingAnnotationError:\n    # add annotations to my_func params, or wrap in a lambda","preventionTips":["Annotate every parameter of any function used as an event trigger","Prefer @rx.event state handlers and lambdas for triggers"],"tags":["reflex","event-handler","type-annotation"],"backgroundTag":"missing-type-annotation","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}