{"record":{"id":"74ca7bcd17b4c02d","repo":"reflex-dev/reflex","slug":"debounceinput-child-requires-an-on-change-handler","errorCode":null,"errorMessage":"DebounceInput child requires an on_change handler","messagePattern":"DebounceInput child requires an on_change handler","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/reflex-components-core/src/reflex_components_core/core/debounce.py","lineNumber":89,"sourceCode":"\n        Returns:\n            The DebounceInput component.\n\n        Raises:\n            RuntimeError: unless exactly one child element is provided.\n            ValueError: if the child element does not have an on_change handler.\n        \"\"\"\n        if len(children) != 1:\n            msg = (\n                \"Provide a single child for DebounceInput, such as rx.input() or \"\n                \"rx.text_area()\"\n            )\n            raise RuntimeError(msg)\n\n        child = children[0]\n        if \"on_change\" not in child.event_triggers:\n            msg = \"DebounceInput child requires an on_change handler\"\n            raise ValueError(msg)\n\n        # Carry known props and event_triggers from the child.\n        props_from_child = {\n            p: getattr(child, p)\n            for p in cls.get_props()\n            if getattr(child, p, None) is not None\n        }\n        props[EventTriggers.ON_CHANGE] = child.event_triggers.pop(\n            EventTriggers.ON_CHANGE\n        )\n        props = {**props_from_child, **props}\n\n        # Carry all other child props directly via custom_attrs\n        other_props = {\n            p: getattr(child, p)\n            for p in child.get_props()\n            if p not in props_from_child and getattr(child, p) is not None\n        }","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/reflex-dev/reflex/blob/45b8ed5ab735f8a56bbb09a42384f030eb0208e7/packages/reflex-components-core/src/reflex_components_core/core/debounce.py#L71-L107","documentation":"DebounceInput works by intercepting the child's on_change event and delaying it. If the wrapped input has no on_change handler, there is nothing to debounce, so creation fails.","triggerScenarios":"`rx.debounce_input(rx.input(placeholder='search'))` with no on_change; wrapping a read-only or display-only input.","commonSituations":"Building a search box but wiring the handler later; copy-pasting an input element into debounce_input without its event props.","solutions":["Add an on_change handler to the child input: rx.debounce_input(rx.input(on_change=State.set_query))","If you don't need debouncing, use the plain input without rx.debounce_input"],"exampleFix":"// before\nrx.debounce_input(rx.input(placeholder='Search'))\n// after\nrx.debounce_input(rx.input(placeholder='Search', on_change=State.set_query), delay_ms=300)","handlingStrategy":"validation","validationCode":"child = rx.input(value=State.q, on_change=State.set_q)\nrx.debounce_input(child)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always wire on_change on the inner input before wrapping","Debounce only makes sense for inputs that fire on_change"],"tags":["reflex","debounce","event-handler"],"backgroundTag":"missing-event-handler","analyzedSha":"45b8ed5ab735f8a56bbb09a42384f030eb0208e7","analyzedAt":"2026-08-28T19:25:27.644Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}