{"record":{"id":"98c380fe33622d0e","repo":"keras-team/keras","slug":"argument-num-thresholds-must-be-an-integer-0","errorCode":null,"errorMessage":"Argument `num_thresholds` must be an integer > 0. Received: num_thresholds={num_thresholds}","messagePattern":"Argument `num_thresholds` must be an integer > 0\\. Received: num_thresholds=(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"keras/src/metrics/confusion_metrics.py","lineNumber":573,"sourceCode":"        return {**base_config, **config}\n\n\nclass SensitivitySpecificityBase(Metric):\n    \"\"\"Abstract base class for computing sensitivity and specificity.\n\n    For additional information about specificity and sensitivity, see\n    [the following](https://en.wikipedia.org/wiki/Sensitivity_and_specificity).\n    \"\"\"\n\n    def __init__(\n        self, value, num_thresholds=200, class_id=None, name=None, dtype=None\n    ):\n        super().__init__(name=name, dtype=dtype)\n        # Metric should be maximized during optimization.\n        self._direction = \"up\"\n\n        if num_thresholds <= 0:\n            raise ValueError(\n                \"Argument `num_thresholds` must be an integer > 0. \"\n                f\"Received: num_thresholds={num_thresholds}\"\n            )\n        self.value = value\n        self.class_id = class_id\n\n        # Compute `num_thresholds` thresholds in [0, 1]\n        if num_thresholds == 1:\n            self.thresholds = [0.5]\n            self._thresholds_distributed_evenly = False\n        else:\n            thresholds = [\n                (i + 1) * 1.0 / (num_thresholds - 1)\n                for i in range(num_thresholds - 2)\n            ]\n            self.thresholds = [0.0] + thresholds + [1.0]\n            self._thresholds_distributed_evenly = True\n","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/keras-team/keras/blob/7a34a03db60bf60042242d6a556fc3be119046a5/keras/src/metrics/confusion_metrics.py#L555-L591","documentation":"Raised by the constructor of sensitivity/specificity-style confusion metrics (keras/src/metrics/confusion_metrics.py:573) when num_thresholds is zero or negative. Keras discretizes the ROC/PR curve into num_thresholds buckets, so it must be a positive integer. The check runs eagerly in __init__, before any data is seen.","triggerScenarios":"keras.metrics.SpecificityAtSensitivity(0.5, num_thresholds=0); negative values; values computed from config that evaluate to 0 (e.g. int(cfg['steps'])).","commonSituations":"Hyperparameter sweeps including 0 or -1 sentinels; YAML/JSON configs where num_thresholds is missing and defaults to 0; code ported from older TF that used num_thresholds=1.","solutions":["Set num_thresholds to a positive integer, typically 200 (default) or 500-1000 for finer resolution.","Validate config values before constructing the metric.","Constrain sweeps to num_thresholds >= 2."],"exampleFix":"# before\nm = keras.metrics.SpecificityAtSensitivity(0.5, num_thresholds=0)\n\n# after\nm = keras.metrics.SpecificityAtSensitivity(0.5, num_thresholds=200)","handlingStrategy":"validation","validationCode":"nt = int(num_thresholds)\nif nt <= 0:\n    raise ValueError(f'num_thresholds must be > 0, got {nt}')","typeGuard":"def is_valid_num_thresholds(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and v > 0","tryCatchPattern":null,"preventionTips":["Validate hyperparameters once at config-load time.","Keep num_thresholds at the default 200 unless finer resolution is needed."],"tags":["keras","metrics","num-thresholds"],"backgroundTag":"invalid-argument-range","analyzedSha":"7a34a03db60bf60042242d6a556fc3be119046a5","analyzedAt":"2026-08-25T21:25:25.994Z","schemaVersion":2},"datasetVersion":"2026-08-26T02:17:13.382Z"}