reflex-dev/reflex · error · TypeError

Only Radix TextFieldRoot and DebounceInput are allowed as ch

Error message

Only Radix TextFieldRoot and DebounceInput are allowed as children of FormControl

What it means

rx.form_control only accepts a Radix TextFieldRoot or a DebounceInput as its single child. Any other component (text, select, checkbox, custom component) raises TypeError because the wrapper forwards props like size/invalid specifically to those input types.

Source

Thrown at packages/reflex-components-radix/src/reflex_components_radix/primitives/form.py:112

        Args:
            *children: The children of the form.
            **props: The properties of the form.

        Returns:
            The form control component.

        Raises:
            ValueError: If the number of children is greater than 1.
            TypeError: If a child exists but it is not a TextFieldInput.
        """
        if len(children) > 1:
            msg = f"FormControl can only have at most one child, got {len(children)} children"
            raise ValueError(msg)
        for child in children:
            if not isinstance(child, (TextFieldRoot, DebounceInput)):
                msg = "Only Radix TextFieldRoot and DebounceInput are allowed as children of FormControl"
                raise TypeError(msg)
        return super().create(*children, **props)


LiteralMatcher = Literal[
    "badInput",
    "patternMismatch",
    "rangeOverflow",
    "rangeUnderflow",
    "stepMismatch",
    "tooLong",
    "tooShort",
    "typeMismatch",
    "valid",
    "valueMissing",
]


class FormMessage(FormComponent):

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Use the TextField composite: rx.form_control(rx.text_field.root(rx.text_field.input()))
  2. Use DebounceInput if debouncing is desired: rx.form_control(rx.debounce_input())
  3. For selects/checkboxes use their own themed components (rx.select has its own label/error props) instead of form_control

Example fix

# before
rx.form_control(rx.input(placeholder='Name'))
# after
rx.form_control(rx.text_field.root(rx.text_field.input(placeholder='Name')))
Defensive patterns

Strategy: type-guard

Validate before calling

from reflex_components_radix.primitives.text_field import TextFieldRoot
assert isinstance(child, (TextFieldRoot, DebounceInput))

Type guard

def is_allowed_form_child(c) -> bool:
    from reflex_components_radix.primitives.text_field import TextFieldRoot
    from reflex.components.core.debounce import DebounceInput
    return isinstance(c, (TextFieldRoot, DebounceInput))

Prevention

When it happens

Trigger: rx.form_control(rx.select(...)), rx.form_control(rx.checkbox(...)), or rx.form_control(rx.input(...)) (the non-TextField input).

Common situations: Migrating from plain rx.form_control(rx.input()) patterns; wrapping native or third-party inputs in the themed form control.

Related errors


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/44c833698797dabf. Report an issue: GitHub.