keras-team/keras · error · TypeError

`f` should be a callable. Received: f=

Error message

`f` should be a callable. Received: f={f}

What it means

Type guard at the top of the NumPy backend's `scan` (the function `keras.ops.map` delegates to): before scanning, it verifies that the step function `f` is callable, because the whole operation consists of repeatedly applying f to a carry and an input. Passing a lambda result, a non-function object, or a tensor triggers this TypeError naming the received value of f.

Solutions

  1. Pass the function itself, not its result: scan(fn, init, xs) where fn is a def/lambda taking (carry, x)
  2. Wrap a non-callable step in a lambda: lambda carry, x: (carry, some_value)
  3. Check that a method reference was not accidentally invoked with parentheses at the call site
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at keras/src/backend/numpy/ops/core.py:164 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25). Data as JSON: /api/errors/f705730431a0bd80. Report an issue: GitHub.

Appendix: source

Thrown at keras/src/backend/numpy/ops/core.py:164

                return KerasTensor(x.shape, standardize_dtype(x.dtype))
            return x

        output_spec = tree.map_structure(convert_numpy_to_keras_tensor, outputs)
    return output_spec


def map(f, xs):
    def g(_, x):
        return (), f(x)

    _, ys = scan(g, (), xs)
    return ys


def scan(f, init, xs=None, length=None, reverse=False, unroll=1):
    # Ref: jax.lax.scan
    if not callable(f):
        raise TypeError(f"`f` should be a callable. Received: f={f}")
    if not isinstance(unroll, bool):
        if not isinstance(unroll, int) or unroll < 1:
            raise ValueError(
                "`unroll` must be an positive integer or boolean. "
                f"Received: unroll={unroll}"
            )
    if xs is None and length is None:
        raise ValueError("Got no `xs` to scan over and `length` not provided.")

    input_is_sequence = tree.is_nested(xs)
    output_is_sequence = tree.is_nested(init)

    def pack_input(x):
        return tree.pack_sequence_as(xs, x) if input_is_sequence else x[0]

    def pack_output(x):
        return tree.pack_sequence_as(init, x) if output_is_sequence else x[0]

View on GitHub (pinned to 7a34a03db6)