keras-team/keras · error · TypeError

adapt() expects an iterable that yields arrays or tensors wi

Error message

adapt() expects an iterable that yields arrays or tensors with a `.shape` attribute (e.g. numpy arrays or backend tensors). Got an element of type {type(first_batch).__name__}. Ensure each yielded element is array-like with a `.shape` attribute.

What it means

adapt() on a generic iterable infers the input shape from the first yielded element's .shape attribute. If the element lacks .shape (plain list, tuple, scalar, dict), a TypeError is raised naming the offending type.

Source

Thrown at keras/src/layers/preprocessing/normalization.py:310

        elif isinstance(data, PyDataset):
            input_shape = _extract_batch(data[0]).shape
        elif hasattr(data, "__iter__"):
            data_is_iterable = True
            # Consume first batch to infer input_shape; then chain it back for
            # accumulation so we iterate over (first_batch, *rest).
            data_iter = iter(data)
            first_batch = next(data_iter, None)
            if first_batch is None:
                raise ValueError(
                    "adapt() received an empty iterable (no batches). "
                    "Expected at least one batch. Pass a non-empty iterable "
                    "of arrays or tensors, e.g. layer.adapt([x]) or "
                    "layer.adapt(list_of_batches)."
                )
            first_batch = _extract_batch(first_batch)
            input_shape = getattr(first_batch, "shape", None)
            if input_shape is None:
                raise TypeError(
                    "adapt() expects an iterable that yields arrays or "
                    "tensors with a `.shape` attribute (e.g. numpy arrays or "
                    "backend tensors). Got an element of type "
                    f"{type(first_batch).__name__}. Ensure each yielded "
                    "element is array-like with a `.shape` attribute."
                )
            input_shape = tuple(input_shape)
            data = itertools.chain([first_batch], data_iter)
        else:
            raise TypeError(
                f"Unsupported data type: {type(data)}. `adapt` supports "
                f"`np.ndarray`, backend tensors, `tf.data.Dataset`, "
                f"`keras.utils.PyDataset`, and iterables of batches (e.g. "
                f"list, generator)."
            )

        if not self.built:
            self.build(input_shape)

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Convert to numpy first: layer.adapt(np.array(data))
  2. Convert each element: layer.adapt([np.asarray(b) for b in batches])
  3. For raw arrays pass the array/tensor directly, not wrapped in an iterable

Example fix

// before
layer.adapt([[1.0,2.0],[3.0,4.0]])
// after
import numpy as np
layer.adapt(np.array([[1.0,2.0],[3.0,4.0]]))
Defensive patterns

Strategy: type-guard

Validate before calling

first = next(iter(data))
if not hasattr(first, 'shape'):
    data = [np.asarray(b) for b in data]

Type guard

def batch_is_arraylike(b): return hasattr(b, 'shape')

Prevention

When it happens

Trigger: layer.adapt([[1,2],[3,4]]) where elements are plain Python lists; adapt(zip(a,b)); adapting an iterable of scalars.

Common situations: Notebook prototypes passing raw nested lists; forgetting to convert a list-of-lists to np.ndarray; adapting over zipped columns.

Related errors


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