keras-team/keras · error · ValueError

Argument `trainable_variables` must be a list of tensors cor

Error message

Argument `trainable_variables` must be a list of tensors corresponding 1:1 to {self.__class__.__name__}().trainable_variables. Received list with length {len(trainable_variables)}, but expected {len(self.trainable_variables)} variables.

What it means

stateless_call() requires the trainable_variables list to match the layer's own trainable_variables 1:1, in the same order. A length mismatch means you passed a wrong or partial set of variables (often from a different layer or the whole model).

Source

Thrown at keras/src/layers/layer.py:1151

            data,
        )
        # Attach the updated state to the model
        # (until you do this, the model is still in its pre-call state).
        for ref_var, value in zip(
            model.non_trainable_variables, non_trainable_variables
        ):
            ref_var.assign(value)
        ```
        """
        self._check_super_called()
        if not self.built:
            raise ValueError(
                f"To call stateless_call, {self.__class__.__name__} must be "
                "built (i.e. its variables must have been already created). "
                "You can build it by calling it on some data."
            )
        if len(trainable_variables) != len(self.trainable_variables):
            raise ValueError(
                "Argument `trainable_variables` must be a list of tensors "
                "corresponding 1:1 to "
                f"{self.__class__.__name__}().trainable_variables. "
                f"Received list with length {len(trainable_variables)}, "
                f"but expected {len(self.trainable_variables)} variables."
            )
        if len(non_trainable_variables) != len(self.non_trainable_variables):
            raise ValueError(
                "Argument `non_trainable_variables` must be a list of tensors "
                "corresponding 1:1 to "
                f"{self.__class__.__name__}().non_trainable_variables. "
                f"Received list with length {len(non_trainable_variables)}, "
                f"but expected {len(self.non_trainable_variables)} variables."
            )

        # Gather variable mapping
        trainable_mapping = zip(self.trainable_variables, trainable_variables)
        non_trainable_mapping = zip(

View on GitHub (pinned to 7a34a03db6)

Solutions

  1. Pass exactly layer.trainable_variables (same object, same order) for that layer
  2. If operating on a model, use the model-level functional API rather than per-layer stateless_call

Example fix

# before
out, nw = layer.stateless_call(x, model.trainable_variables, [])
# after
out, nw = layer.stateless_call(x, layer.trainable_variables, layer.non_trainable_variables)
Defensive patterns

Strategy: validation

Validate before calling

assert len(trainable_variables) == len(layer.trainable_variables)

Type guard

def vars_match(layer, tv):
    return len(tv) == len(layer.trainable_variables)

Prevention

When it happens

Trigger: Passing model.trainable_variables to a sublayer's stateless_call; passing variables from before a rebuild; omitting or duplicating an entry.

Common situations: Functional (JAX-style) training loops where variables are gathered globally then handed to individual layers; refactoring after adding new variables.

Related errors


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