{"record":{"id":"20407767d73a8562","repo":"keras-team/keras","slug":"target-class-id-max-target-class-ids-is-out-of","errorCode":null,"errorMessage":"Target class id {max(target_class_ids)} is out of range, which is [{0}, {num_classes}).","messagePattern":"Target class id (.+?) is out of range, which is \\[(.+?), (.+?)\\)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/metrics/iou_metrics.py","lineNumber":275,"sourceCode":"        target_class_ids,\n        name=None,\n        dtype=None,\n        ignore_class=None,\n        sparse_y_true=True,\n        sparse_y_pred=True,\n        axis=-1,\n    ):\n        super().__init__(\n            name=name,\n            num_classes=num_classes,\n            ignore_class=ignore_class,\n            sparse_y_true=sparse_y_true,\n            sparse_y_pred=sparse_y_pred,\n            axis=axis,\n            dtype=dtype,\n        )\n        if max(target_class_ids) >= num_classes:\n            raise ValueError(\n                f\"Target class id {max(target_class_ids)} \"\n                \"is out of range, which is \"\n                f\"[{0}, {num_classes}).\"\n            )\n        self.target_class_ids = list(target_class_ids)\n\n    def result(self):\n        \"\"\"Compute the intersection-over-union via the confusion matrix.\"\"\"\n        sum_over_row = ops.cast(\n            ops.sum(self.total_cm, axis=0), dtype=self.dtype\n        )\n        sum_over_col = ops.cast(\n            ops.sum(self.total_cm, axis=1), dtype=self.dtype\n        )\n        true_positives = ops.cast(ops.diag(self.total_cm), dtype=self.dtype)\n\n        # sum_over_row + sum_over_col =\n        #     2 * true_positives + false_positives + false_negatives.","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/metrics/iou_metrics.py#L257-L293","documentation":"Raised by keras.metrics.IoU's __init__ when the largest id in target_class_ids is >= num_classes. Class ids index a num_classes-sized confusion matrix, so every target id must lie in [0, num_classes).","triggerScenarios":"keras.metrics.IoU(num_classes=3, target_class_ids=[0, 1, 2, 5]); off-by-one num_classes=3 with target id 3; ids from a dataset with a larger label space than num_classes declares.","commonSituations":"num_classes from config while target ids cover more classes; forgetting ids are 0-based so max valid id is num_classes-1; including a background/ignore id beyond range.","solutions":["Set num_classes to at least max(target_class_ids) + 1.","Verify ids are 0-based; for 1..N labels either subtract 1 or set num_classes=N+1.","Sanity-check in setup code: assert max(target_class_ids) < num_classes."],"exampleFix":"# before\nm = keras.metrics.IoU(num_classes=3, target_class_ids=[0, 1, 2, 3])\n\n# after\nm = keras.metrics.IoU(num_classes=4, target_class_ids=[0, 1, 2, 3])\n# or score only classes 0-2 of a 4-class problem:\nm = keras.metrics.IoU(num_classes=4, target_class_ids=[0, 1, 2])","handlingStrategy":"validation","validationCode":"assert max(target_class_ids) < num_classes, (target_class_ids, num_classes)","typeGuard":"def ids_in_range(ids, num_classes) -> bool:\n    return max(ids) < num_classes and min(ids) >= 0","tryCatchPattern":null,"preventionTips":["Derive num_classes from the dataset, not a hand-typed constant.","Remember ids are 0-based; max valid id is num_classes-1."],"tags":["keras","metrics","iou","segmentation","off-by-one"],"backgroundTag":"index-out-of-range","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}