reflex-dev/reflex · error · ForeachRenderError

Expected 1 or 2 parameters in foreach render function, got {

Error message

Expected 1 or 2 parameters in foreach render function, got {[p.name for p in params]}. See https://reflex.dev/docs/library/dynamic-rendering/foreach/

What it means

The render function passed to `rx.foreach` may accept 1 parameter (the item) or 2 parameters (item, index) for lists, or (key, value) for dicts. Zero or more than two parameters — including params with defaults counting toward the signature — raise ForeachRenderError.

Source

Thrown at packages/reflex-components-core/src/reflex_components_core/core/foreach.py:137

                "foreach",
                "https://reflex.dev/docs/library/dynamic-rendering/foreach/",
            ).with_traceback(e.__traceback__) from None
        return component

    def _render(self) -> IterTag:
        props = {}

        render_sig = inspect.signature(self.render_fn)
        params = list(render_sig.parameters.values())

        # Validate the render function signature.
        if len(params) == 0 or len(params) > 2:
            msg = (
                "Expected 1 or 2 parameters in foreach render function, got "
                f"{[p.name for p in params]}. See "
                "https://reflex.dev/docs/library/dynamic-rendering/foreach/"
            )
            raise ForeachRenderError(msg)

        if len(params) >= 1:
            # Determine the arg var name based on the params accepted by render_fn.
            props["arg_var_name"] = params[0].name + FIELD_MARKER

        if len(params) == 2:
            # Determine the index var name based on the params accepted by render_fn.
            props["index_var_name"] = params[1].name + FIELD_MARKER
        else:
            render_fn = self.render_fn
            # Otherwise, use a deterministic index, based on the render function bytecode.
            if (render_fn_code := getattr(render_fn, "__code__", None)) is not None:
                code_hash = md5(render_fn_code.co_code).hexdigest()
            elif isinstance(render_fn, functools.partial):
                code_hash = md5(render_fn.func.__code__.co_code).hexdigest()
            else:
                code_hash = md5(repr(render_fn).encode()).hexdigest()
            props["index_var_name"] = f"index_{code_hash}"

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Use exactly one parameter: rx.foreach(State.items, lambda item: rx.text(item))
  2. Or two for index access: rx.foreach(State.items, lambda item, i: rx.text(f'{i}: {item}'))
  3. Wrap multi-arg builders in a closure: lambda item: make_row(item, 'extra')

Example fix

# before
def render_row(item, index, is_admin): ...
rx.foreach(State.items, render_row)
# after
rx.foreach(State.items, lambda item, i: render_row(item, i, State.is_admin))
Defensive patterns

Strategy: validation

Validate before calling

import inspect
params = inspect.signature(render_fn).parameters
assert 1 <= len(params) <= 2, f'render fn takes 1-2 params, got {len(params)}'

Type guard

def valid_foreach_fn(fn) -> bool:
    import inspect
    return 1 <= len(inspect.signature(fn).parameters) <= 2

Prevention

When it happens

Trigger: `rx.foreach(State.items, lambda: rx.text('x'))`; a render def with three params like def render(item, index, extra); accidentally passing a component class constructor expecting many args.

Common situations: Reusing a component factory function with extra arguments; refactoring a render fn and leaving stale parameters.

Related errors


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