keras-team/keras · error · ValueError
All `axis` values to be kept must have a known shape…
Error message
All `axis` values to be kept must have a known shape. Received axis={self.axis}, inputs.shape={input_shape}, with unknown axis at index {d} What it means
Raised by Normalization.compute_output_shape() when one of the axes the layer keeps has an unknown (None) dimension in the input shape. Every axis listed in self.axis must have a known dimension so the normalization statistics can broadcast correctly.
Solutions
- Specify a concrete feature dimension in the input, e.g. keras.Input(shape=(max_len, n_features))
- Normalize an axis whose size is known
- Pad or truncate inputs so the kept axis has a static size
Example fix
// before inputs = keras.Input(shape=(None,)) # unknown last dim norm = Normalization(axis=-1)(inputs) // after inputs = keras.Input(shape=(256,)) norm = Normalization(axis=-1)(inputs)
Defensive patterns
Strategy: validation
Validate before calling
for d in [d if d >= 0 else d + ndim for d in axis_list]:
assert input_shape[d] is not None, f'axis {d} must have a static size' Prevention
- Always give keras.Input an explicit feature dimension
- Avoid None dims on normalized axes
When it happens
Trigger: Feeding symbolic tensors with an unknown feature dimension, e.g. input shape (None, None), into Normalization(axis=-1); functional models built from TensorSpec(shape=[None,None]).
Common situations: Variable-length inputs without a fixed feature width; converting eager code to a graph where the last dim was implicit.
Related errors
- All `axis` values must be in the range
- adapt() expects an iterable that yields arrays or tensors…
- adapt() received an empty iterable (no batches). Expected…
- Cannot infer argument `num` from shape
- Cannot quantize a layer that isn't yet built. Layer
AI-assisted analysis of keras-team/keras@7a34a03db6 (2026-08-25).
Data as JSON: /api/errors/81e407aaed903140.
Report an issue: GitHub.
Appendix: source
Thrown at keras/src/layers/preprocessing/normalization.py:175
ndim = len(input_shape)
self._build_input_shape = input_shape
if any(a < -ndim or a >= ndim for a in self.axis):
raise ValueError(
"All `axis` values must be in the range [-ndim, ndim). "
f"Received inputs with ndim={ndim}, while axis={self.axis}"
)
# Axes to be kept, replacing negative values with positive equivalents.
# Sorted to avoid transposing axes.
self._keep_axis = tuple(
sorted([d if d >= 0 else d + ndim for d in self.axis])
)
# All axes to be kept should have known shape.
for d in self._keep_axis:
if input_shape[d] is None:
raise ValueError(
"All `axis` values to be kept must have a known shape. "
f"Received axis={self.axis}, "
f"inputs.shape={input_shape}, "
f"with unknown axis at index {d}"
)
# Axes to be reduced.
self._reduce_axis = tuple(
d for d in range(ndim) if d not in self._keep_axis
)
# 1 if an axis should be reduced, 0 otherwise.
self._reduce_axis_mask = [
0 if d in self._keep_axis else 1 for d in range(ndim)
]
# Broadcast any reduced axes.
self._broadcast_shape = [
input_shape[d] if d in self._keep_axis else 1 for d in range(ndim)
]
mean_and_var_shape = tuple(input_shape[d] for d in self._keep_axis)View on GitHub (pinned to 7a34a03db6)