reflex-dev/reflex · error · TypeError

Compiled page {route!r} root must be a Component before it c

Error message

Compiled page {route!r} root must be a Component before it can be registered on the app.

What it means

During compile_app, after evaluating a page, its root_component must be a Component before being registered in app._pages. This guards against page functions that evaluate to a non-Component root (e.g. returning a primitive or None), preventing corrupt page registration.

Source

Thrown at reflex/compiler/compiler.py:1241

        hooks=CompilerHooks(
            plugins=default_page_plugins(style=app.style, plugins=compiler_plugins)
        ),
    )

    with log.timing(logger, "Compile pages"), compile_ctx:
        compile_ctx.compile(
            evaluate_progress=lambda: progress.advance(task),
            render_progress=lambda: progress.advance(task),
        )

    for route, page_ctx in compile_ctx.compiled_pages.items():
        app._check_routes_conflict(route)
        if not isinstance(page_ctx.root_component, Component):
            msg = (
                f"Compiled page {route!r} root must be a Component before it can "
                "be registered on the app."
            )
            raise TypeError(msg)
        app._pages[route] = page_ctx.root_component

    app._evaluated_pages.update(compile_ctx.compiled_pages)
    app._stateful_pages.update(compile_ctx.stateful_routes)
    app._write_stateful_pages_marker()
    app._add_optional_endpoints()
    app._validate_var_dependencies()

    if config.show_built_with_reflex is None:
        if (
            get_compile_context() == constants.CompileContext.DEPLOY
            and prerequisites.get_user_tier() in ["pro", "team", "enterprise"]
        ):
            config.show_built_with_reflex = False
        else:
            config.show_built_with_reflex = True

    if is_prod_mode() and config.show_built_with_reflex:

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Make the page function always return a Component (e.g. rx.fragment() for empty states)
  2. Verify add_page is given a function that returns components, not a component instance called with wrong args
  3. Add a unit test asserting the page function's return type

Example fix

# before
def index():
    if State.error:
        return
    return rx.text("ok")
# after
def index():
    if State.error:
        return rx.fragment()
    return rx.text("ok")
Defensive patterns

Strategy: validation

Validate before calling

def _check(page):
    root = page()
    if root is not None and not isinstance(root, (rx.Component, str, rx.Var)):
        raise TypeError(f"page returns non-renderable {type(root)}")

Type guard

def is_renderable(v) -> bool:
    return v is None or isinstance(v, (rx.Component, str, rx.Var))

Prevention

When it happens

Trigger: add_page() with a page function whose return value converts to a non-Component (raw None from an early return, an int, or a misused component factory), or a custom page/UnevaluatedPage pipeline producing a bad root.

Common situations: Pages with conditional returns that fall through to None, refactoring render functions to return data instead of components, or dynamic pages built by plugins wrapping add_page.

Related errors


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