{"record":{"id":"557d5e3878f7b704","repo":"keras-team/keras","slug":"invalid-images-rank-expected-rank-3-single-image-557d5e","errorCode":null,"errorMessage":"Invalid images rank: expected rank 3 (single image) or rank 4 (batch of images). Received: images.shape={images_shape}","messagePattern":"Invalid images rank: expected rank 3 \\(single image\\) or rank 4 \\(batch of images\\)\\. Received: images\\.shape=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/ops/image.py","lineNumber":23,"sourceCode":"from keras.src.backend import any_symbolic_tensors\nfrom keras.src.ops.operation import Operation\nfrom keras.src.ops.operation_utils import compute_conv_output_shape\n\n\nclass RGBToGrayscale(Operation):\n    def __init__(self, data_format=None, *, name=None):\n        super().__init__(name=name)\n        self.data_format = backend.standardize_data_format(data_format)\n\n    def call(self, images):\n        return backend.image.rgb_to_grayscale(\n            images, data_format=self.data_format\n        )\n\n    def compute_output_spec(self, images):\n        images_shape = list(images.shape)\n        if len(images_shape) not in (3, 4):\n            raise ValueError(\n                \"Invalid images rank: expected rank 3 (single image) \"\n                \"or rank 4 (batch of images). \"\n                f\"Received: images.shape={images_shape}\"\n            )\n        channels_axis = -1 if self.data_format == \"channels_last\" else -3\n        channels = images_shape[channels_axis]\n        if channels is not None and channels not in (1, 3):\n            raise ValueError(\n                \"Invalid channel size: expected 3 (RGB) or 1 (Grayscale). \"\n                f\"Received input with shape: images.shape={tuple(images_shape)}\"\n            )\n        images_shape[channels_axis] = 1\n        return KerasTensor(shape=images_shape, dtype=images.dtype)\n\n\n@keras_export(\"keras.ops.image.rgb_to_grayscale\")\ndef rgb_to_grayscale(images, data_format=None):\n    \"\"\"Convert RGB images to grayscale.","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/ops/image.py#L5-L41","documentation":"This is the output-spec computation of the grayscale-to-RGB style image op (keras/src/ops/image.py auto_schedule/grayscale family): the images argument must be rank 3 (H, W, C) or rank 4 (N, H, W, C). Any other rank (e.g. rank 2 or rank 5) is rejected before channel logic runs.","triggerScenarios":"Calling the op on a raw rank-2 array (no channel axis) or a rank-5 stack of batches; calling with data_format mismatch such that an extra axis is interpreted incorrectly.","commonSituations":"Loading grayscale masks stored as (H, W) without adding a channel dim; wrapping data in nested batches twice; mixing channels_first data passed without setting data_format.","solutions":["Reshape input to rank 3 or 4: x = x[..., None] for (H,W) input or np.expand_dims(x, 0) to batch a single image","If data is channels_first, pass data_format='channels_first' explicitly","Verify no double batching (two stacked batch axes) in the data pipeline"],"exampleFix":"# before\ny = op(images)  # images.shape=(224,224)\n\n# after\nimages = images[..., None]  # (224,224,1)\ny = op(images)","handlingStrategy":"validation","validationCode":"assert len(images.shape) in (3, 4), f'bad rank: {images.shape}'","typeGuard":"def is_valid_image_rank(images) -> bool:\n    return len(getattr(images, 'shape', ())) in (3, 4)","tryCatchPattern":"try:\n    y = op(images)\nexcept ValueError:\n    images = images[..., None] if len(images.shape) == 2 else images\n    y = op(images)","preventionTips":["Standardize images to rank 4 (N,H,W,C) at pipeline entry","Wrap dataset yields with a shape assert during development"],"tags":["keras","image","rank-validation","shape-mismatch"],"backgroundTag":"image-rank-validation","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}