From dafc86fdff45d48a456c246e022c1d493ac4a930 Mon Sep 17 00:00:00 2001 From: WatchTree-19 <119982314+WatchTree-19@users.noreply.github.com> Date: Sun, 15 Nov 2026 02:22:06 +0000 Subject: [PATCH] Reject NaN increments on Counter Counter.inc rejected negative amounts but accepted NaN, which left the counter's total at NaN from then on. OpenMetrics requires a counter's total to be non-NaN and monotonically non-decreasing, so a NaN increment now raises ValueError and the total is left unchanged. Signed-off-by: WatchTree-19 <119982314+WatchTree-19@users.noreply.github.com> --- prometheus_client/metrics.py | 2 ++ tests/test_core.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/prometheus_client/metrics.py b/prometheus_client/metrics.py index a0ad9b92..8e0d74d4 100644 --- a/prometheus_client/metrics.py +++ b/prometheus_client/metrics.py @@ -347,6 +347,8 @@ def inc(self, amount: float = 1, exemplar: Optional[Dict[str, str]] = None) -> N self._raise_if_not_observable() if amount < 0: raise ValueError('Counters can only be incremented by non-negative amounts.') + if math.isnan(amount): + raise ValueError('Counters cannot be incremented by NaN.') self._value.inc(amount) if exemplar: _validate_exemplar(exemplar) diff --git a/tests/test_core.py b/tests/test_core.py index 2ed2da90..e0ec830a 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -71,6 +71,11 @@ def test_clear_without_labels_is_noop(self): def test_negative_increment_raises(self): self.assertRaises(ValueError, self.counter.inc, -1) + def test_nan_increment_raises(self): + self.counter.inc(2) + self.assertRaises(ValueError, self.counter.inc, float('nan')) + self.assertEqual(2, self.registry.get_sample_value('c_total')) + def test_function_decorator(self): @self.counter.count_exceptions(ValueError) def f(r):