reflex-dev/reflex · error · ValueError

f"Invalid variant: {variant}. Available variants: {available

Error message

f"Invalid variant: {variant}. Available variants: {available_variants}"

What it means

The internal Button component validates its variant against the allowed variants (e.g. classic, solid, soft, surface, outline, ghost). An unknown variant string raises this.

Source

Thrown at packages/reflex-components-internal/src/reflex_components_internal/components/base/button.py:122

        if isinstance(loading, Var):
            props["disabled"] = cond(loading, True, disabled)
            children_list.insert(0, cond(loading, spinner()))
        else:
            props["disabled"] = True if loading else disabled
            children_list.insert(0, spinner()) if loading else None

        return super().create(*children_list, **props)

    @staticmethod
    def validate_variant(variant: LiteralButtonVariant):
        """Validate the button variant."""
        if variant not in BUTTON_VARIANTS["variant"]:
            available_variants = ", ".join(BUTTON_VARIANTS["variant"].keys())
            message = (
                f"Invalid variant: {variant}. Available variants: {available_variants}"
            )
            raise ValueError(message)

    @staticmethod
    def validate_size(size: LiteralButtonSize):
        """Validate the button size."""
        if size not in BUTTON_VARIANTS["size"]:
            available_sizes = ", ".join(BUTTON_VARIANTS["size"].keys())
            message = f"Invalid size: {size}. Available sizes: {available_sizes}"
            raise ValueError(message)

    def _exclude_props(self) -> list[str]:
        return [
            *super()._exclude_props(),
            "size",
            "variant",
            "loading",
        ]

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Use one of the listed variants in the error message, e.g. variant="solid" or "soft"
  2. If the value is dynamic, constrain it to the Literal type (rx.button variants) so your type checker catches it
  3. For legacy Chakra variants, map them during migration (primary→solid, link→ghost)

Example fix

# before
rx.button("Hi", variant="primary")
# after
rx.button("Hi", variant="solid")
Defensive patterns

Strategy: type-guard

Validate before calling

ALLOWED = {'classic', 'solid', 'soft', 'surface', 'outline', 'ghost'}
if variant not in ALLOWED:
    variant = 'solid'  # or log & fall back

Type guard

def is_valid_button_variant(v: str) -> TypeGuard[str]:
    from reflex_components_internal.components.base.button import BUTTON_VARIANTS
    return v in BUTTON_VARIANTS['variant']

Prevention

When it happens

Trigger: rx.button("Hi", variant="primary") — 'primary' is not in BUTTON_VARIANTS; typos or theme keys from other UI libraries (chakra-era names) trigger it.

Common situations: Migrating old Reflex (Chakra) code using variant="solid"/"primary" or "link" to the new internal components; passing a dynamically-built variant string with a bad value.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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