{"record":{"id":"b65f13ea133ed740","repo":"keras-team/keras","slug":"if-bounding-boxes-boxes-is-a-ragged-tensor","errorCode":null,"errorMessage":"If `bounding_boxes['boxes']` is a Ragged tensor,  `bounding_boxes['labels']` must also be a Ragged tensor. Received: bounding_boxes['labels']={labels}","messagePattern":"If `bounding_boxes\\['boxes'\\]` is a Ragged tensor,  `bounding_boxes\\['labels'\\]` must also be a Ragged tensor\\. Received: bounding_boxes\\['labels'\\]=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/layers/preprocessing/image_preprocessing/bounding_boxes/validation.py","lineNumber":148,"sourceCode":"    labels = bounding_boxes[\"labels\"]\n    if isinstance(boxes, list):\n        if not isinstance(labels, list):\n            raise ValueError(\n                \"If `bounding_boxes['boxes']` is a list, then \"\n                \"`bounding_boxes['labels']` must also be a list.\"\n                f\"Received: bounding_boxes['labels']={labels}\"\n            )\n        if len(boxes) != len(labels):\n            raise ValueError(\n                \"If `bounding_boxes['boxes']` and \"\n                \"`bounding_boxes['labels']` are both lists, \"\n                \"they must have the same length. Received: \"\n                f\"len(bounding_boxes['boxes'])={len(boxes)} and \"\n                f\"len(bounding_boxes['labels'])={len(labels)} and \"\n            )\n    elif tf_utils.is_ragged_tensor(boxes):\n        if not tf_utils.is_ragged_tensor(labels):\n            raise ValueError(\n                \"If `bounding_boxes['boxes']` is a Ragged tensor, \"\n                \" `bounding_boxes['labels']` must also be a \"\n                \"Ragged tensor. \"\n                f\"Received: bounding_boxes['labels']={labels}\"\n            )\n    else:\n        boxes_shape = current_backend.shape(boxes)\n        labels_shape = current_backend.shape(labels)\n        if len(boxes_shape) == 2:  # (boxes, 4)\n            if len(labels_shape) not in {1, 2}:\n                raise ValueError(\n                    \"Found \"\n                    f\"bounding_boxes['boxes'].shape={boxes_shape} \"\n                    \"and expected bounding_boxes['labels'] to have \"\n                    \"rank 1 or 2, but received: \"\n                    f\"bounding_boxes['labels'].shape={labels_shape} \"\n                )\n        elif len(boxes_shape) == 3:","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/layers/preprocessing/image_preprocessing/bounding_boxes/validation.py#L130-L166","documentation":"If 'boxes' is a RaggedTensor, validate_bounding_boxes requires 'labels' to be a RaggedTensor too, because raggedness encodes the per-image box counts and must match on both sides. A dense tensor or list for labels cannot be aligned with ragged boxes.","triggerScenarios":"densify_bounding_boxes with boxes as a tf.RaggedTensor (batch of varying box counts) but labels as a dense tensor or Python list.","commonSituations":"tf.data pipelines producing ragged boxes; converting only the boxes side to ragged to handle variable box counts while labels stay dense; TF2 detection data loaders.","solutions":["Convert labels to a RaggedTensor with the same row partition: tf.ragged.constant(list_of_label_arrays)","Or use from_row_splits so labels share boxes.row_splits","Or densify boxes first (pad to max box count), then use dense tensors for both"],"exampleFix":"# before\nbbs = {'boxes': tf.ragged.constant(box_lists), 'labels': np.array(label_lists)}\n# after\nbbs = {'boxes': tf.ragged.constant(box_lists),\n        'labels': tf.ragged.constant(label_lists)}","handlingStrategy":"validation","validationCode":"if hasattr(bbs['boxes'], 'values') and not hasattr(bbs['labels'], 'values'):\n    import tensorflow as tf\n    bbs['labels'] = tf.ragged.stack(list(bbs['labels']))","typeGuard":"def boxes_labels_same_raggedness(bbs):\n    b, l = bbs['boxes'], bbs['labels']\n    return hasattr(b, 'values') == hasattr(l, 'values')","tryCatchPattern":null,"preventionTips":["Build both ragged tensors with the same row_splits in the data pipeline","Or keep both sides dense and pad to a fixed box count"],"tags":["keras","ragged-tensor","bounding-boxes","tensorflow"],"backgroundTag":"input-shape-validation-failed","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}