reflex-dev/reflex · error · ValueError

Route part `{part}` with optional argument is not valid. Ref

Error message

Route part `{part}` with optional argument is not valid. Reflex only supports optional arguments that start with an alphabetic character or underscore, followed by alphanumeric characters or underscores.

What it means

Optional route arguments use double-bracket syntax ([[arg]]) and must match RouteRegex.OPTIONAL_ARG: start with a letter or underscore followed by alphanumerics/underscores. Segments like [[1id]], [[my-arg]], or [[]] fail validation in verify_route_validity.

Source

Thrown at reflex/route.py:47

            )
            raise ValueError(msg)
        if part.startswith(("[[...", "[...")):
            if part != constants.RouteRegex.SPLAT_CATCHALL:
                msg = f"Catchall pattern `{part}` is not valid. Only `{constants.RouteRegex.SPLAT_CATCHALL}` is allowed."
                raise ValueError(msg)
            if i != len(route_parts) - 1:
                msg = f"Catchall pattern `{part}` must be at the end of the route."
                raise ValueError(msg)
            continue
        if part.startswith("[["):
            if constants.RouteRegex.OPTIONAL_ARG.fullmatch(part):
                continue
            msg = (
                f"Route part `{part}` with optional argument is not valid. "
                "Reflex only supports optional arguments that start with an alphabetic character or underscore, "
                "followed by alphanumeric characters or underscores."
            )
            raise ValueError(msg)
        if not constants.RouteRegex.ARG.fullmatch(part):
            msg = (
                f"Route part `{part}` with argument is not valid. "
                "Reflex only supports argument names that start with an alphabetic character or underscore, "
                "followed by alphanumeric characters or underscores."
            )
            raise ValueError(msg)


def get_route_args(route: str) -> dict[str, str]:
    """Get the dynamic arguments for the given route.

    Args:
        route: The route to get the arguments for.

    Returns:
        The route arguments.
    """

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Rename the optional arg to a valid identifier: [[my_arg]] or [[id]]
  2. Use single brackets for required args: [id]
  3. Ensure the name starts with a letter or underscore

Example fix

# before
app.add_page(page, route='/item/[[my-arg]]')

# after
app.add_page(page, route='/item/[[my_arg]]')
Defensive patterns

Strategy: validation

Validate before calling

import re
OPTIONAL_ARG = re.compile(r'\[\[[A-Za-z_][A-Za-z0-9_]*\]\]')

def valid_optional(part: str) -> bool:
    return bool(OPTIONAL_ARG.fullmatch(part))

Type guard

def is_valid_route_part(part: str) -> bool:
    import re
    return bool(re.fullmatch(r'\[\[[A-Za-z_][A-Za-z0-9_]*\]\]', part))

Prevention

When it happens

Trigger: app.add_page(page, route='/item/[[123]]') or '/item/[[my-arg]]' — names starting with a digit or containing hyphens/spaces inside double brackets.

Common situations: Using hyphenated slug names from URL conventions (my-arg) inside optional brackets; numeric identifiers as optional arg names.

Related errors


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