keras-team/keras · error · ValueError
Argument `non_trainable_variables` must be a list of tensors
Error message
Argument `non_trainable_variables` must be a list of tensors corresponding 1:1 to {self.__class__.__name__}().non_trainable_variables. Received list with length {len(non_trainable_variables)}, but expected {len(self.non_trainable_variables)} variables. What it means
stateless_call() also validates the non_trainable_variables list length against the layer's own non-trainable variables (BatchNorm moving statistics, quantization scale/zero-point, etc.). A mismatch raises this error before any computation.
Source
Thrown at keras/src/layers/layer.py:1159
```
"""
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(
self.non_trainable_variables, non_trainable_variables
)
mapping = list(trainable_mapping) + list(non_trainable_mapping)
# Caches info about `call()` signature, args, kwargs.
call_spec = CallSpec(
self._call_signature, self._call_context_args, args, kwargs
)View on GitHub (pinned to 7a34a03db6)
Solutions
- Pass exactly layer.non_trainable_variables to stateless_call
- Re-gather variables right before the call if the layer was rebuilt or quantized in between
Example fix
# before out, _ = layer.stateless_call(x, layer.trainable_variables, []) # layer has BN stats # after out, _ = layer.stateless_call(x, layer.trainable_variables, layer.non_trainable_variables)
Defensive patterns
Strategy: validation
Validate before calling
assert len(non_trainable_variables) == len(layer.non_trainable_variables)
Type guard
def nontrainable_match(layer, ntv):
return len(ntv) == len(layer.non_trainable_variables) Prevention
- Account for BN statistics and RNG state in non-trainable lists
- Gather both variable lists from the same layer object at call time
When it happens
Trigger: Passing an empty list for a layer with BN statistics; passing model-level non-trainable variables to a sublayer; forgetting RNG-state variables.
Common situations: Layers with metrics/BN state in functional loops; models quantized after variables were collected; variable set changed between gather and call.
Related errors
- Argument `trainable_variables` must be a list of tensors cor
- If using `weights="imagenet"` as true, `classes` should be 1
- The number of repeats in `EfficientNet` must be > 0. Receive
- If using `weights="imagenet"` as true, `classes` should be 1
- The number of repeats in `EfficientNetV2` must be > 0. Recei
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/2ed4630adfc6d82e.
Report an issue: GitHub.