{"record":{"id":"81e407aaed903140","repo":"keras-team/keras","slug":"all-axis-values-to-be-kept-must-have-a-known-sha","errorCode":null,"errorMessage":"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}","messagePattern":"All `axis` values to be kept must have a known shape\\. Received axis=(.+?), inputs\\.shape=(.+?), with unknown axis at index (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/preprocessing/normalization.py","lineNumber":175,"sourceCode":"\n        ndim = len(input_shape)\n        self._build_input_shape = input_shape\n\n        if any(a < -ndim or a >= ndim for a in self.axis):\n            raise ValueError(\n                \"All `axis` values must be in the range [-ndim, ndim). \"\n                f\"Received inputs with ndim={ndim}, while axis={self.axis}\"\n            )\n\n        # Axes to be kept, replacing negative values with positive equivalents.\n        # Sorted to avoid transposing axes.\n        self._keep_axis = tuple(\n            sorted([d if d >= 0 else d + ndim for d in self.axis])\n        )\n        # All axes to be kept should have known shape.\n        for d in self._keep_axis:\n            if input_shape[d] is None:\n                raise ValueError(\n                    \"All `axis` values to be kept must have a known shape. \"\n                    f\"Received axis={self.axis}, \"\n                    f\"inputs.shape={input_shape}, \"\n                    f\"with unknown axis at index {d}\"\n                )\n        # Axes to be reduced.\n        self._reduce_axis = tuple(\n            d for d in range(ndim) if d not in self._keep_axis\n        )\n        # 1 if an axis should be reduced, 0 otherwise.\n        self._reduce_axis_mask = [\n            0 if d in self._keep_axis else 1 for d in range(ndim)\n        ]\n        # Broadcast any reduced axes.\n        self._broadcast_shape = [\n            input_shape[d] if d in self._keep_axis else 1 for d in range(ndim)\n        ]\n        mean_and_var_shape = tuple(input_shape[d] for d in self._keep_axis)","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/preprocessing/normalization.py#L157-L193","documentation":"Normalization must know the size of every kept axis to size its mean/variance buffers. build() raises when input_shape[d] is None for any kept axis d — i.e. that dimension is dynamic/unknown.","triggerScenarios":"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]).","commonSituations":"Variable-length inputs without a fixed feature width; converting eager code to a graph where the last dim was implicit.","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"],"exampleFix":"// before\ninputs = keras.Input(shape=(None,))  # unknown last dim\nnorm = Normalization(axis=-1)(inputs)\n// after\ninputs = keras.Input(shape=(256,))\nnorm = Normalization(axis=-1)(inputs)","handlingStrategy":"validation","validationCode":"for d in [d if d >= 0 else d + ndim for d in axis_list]:\n    assert input_shape[d] is not None, f'axis {d} must have a static size'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always give keras.Input an explicit feature dimension","Avoid None dims on normalized axes"],"tags":["keras","normalization","dynamic-shape","build"],"backgroundTag":"unknown-dimension-in-shape","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}