reflex-dev/reflex · error · ValueError

The render function must take 2 arguments.

Error message

The render function must take 2 arguments.

What it means

When a `rx.foreach` render function accepts the index (two parameters), Reflex calls it with `(item, index)`. This error means the render function's signature declares it takes the index (arity detected as 2) but Reflex ended up needing exactly two arguments and the function does not accept `(arg, index)` as provided — i.e. the arity contract is broken.

Source

Thrown at packages/reflex-base/src/reflex_base/components/tags/iter_tag.py:100

        from reflex_components_core.base.fragment import Fragment
        from reflex_components_core.core.cond import Cond
        from reflex_components_core.core.foreach import Foreach

        from reflex.compiler.compiler import _into_component_once

        # Get the render function arguments.
        args = inspect.getfullargspec(self.render_fn).args
        arg = self.get_arg_var()
        index = self.get_index_var()

        if len(args) == 1:
            # If the render function doesn't take the index as an argument.
            component = self.render_fn(arg)
        else:
            # If the render function takes the index as an argument.
            if len(args) != 2:
                msg = "The render function must take 2 arguments."
                raise ValueError(msg)
            component = self.render_fn(arg, index)

        # Nested foreach components or cond must be wrapped in fragments.
        if isinstance(component, (Foreach, Cond)):
            component = Fragment.create(component)

        component = _into_component_once(component)

        if component is None:
            msg = "The render function must return a component."
            raise ValueError(msg)

        # Set the component key.
        if component.key is None:
            component.key = index

        return component

View on GitHub (pinned to 45b8ed5ab7)

Solutions

  1. Make the render function take exactly `(item)` or exactly `(item, index)` with no defaults or keyword-only args
  2. Avoid `functools.partial` on render functions; use a closure instead

Example fix

# before
rx.foreach(State.items, lambda item, i=0: rx.text(item, key=i))

# after
rx.foreach(State.items, lambda item, i: rx.text(item, key=i))
Defensive patterns

Strategy: type-guard

Validate before calling

import inspect

def valid_foreach_fn(fn) -> bool:
    params = [p for p in inspect.signature(fn).parameters.values()
              if p.default is inspect.Parameter.empty
              and p.kind in (inspect.Parameter.POSITIONAL_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD)]
    return len(params) in (1, 2)

Type guard

import inspect

def is_valid_render_fn(fn) -> bool:
    """Render fn must take exactly (item) or (item, index), no defaults."""
    ps = list(inspect.signature(fn).parameters.values())
    return all(p.default is inspect.Parameter.empty for p in ps) and len(ps) in (1, 2)

Prevention

When it happens

Trigger: A render function with a mismatched arity, e.g. default/keyword-only arguments making the effective parameter count ambiguous, or manually calling `render_component` with an index when the function takes only one argument plus a defaulted second.

Common situations: Adding a defaulted second parameter (`def render(item, i=0)`) to a foreach render fn, or wrapping a lambda with `functools.partial` that changes the effective arity.

Related errors


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