Repository navigation
Calling clear() on Counter without labels fails #707
Description
Activity
Clear is for clearing a
labelset, so it should bug out here but probably it needs a better error message.If your objective is to set a counter back to some starting value then you are using the wrong metric, you need a
Gauge.
From the information on counter:Do not use a counter to expose a value that can decrease. For example, do not use a counter for the number of currently running processes; instead use a gauge.
Exactly. We would benefit for a better error message.
I also thought
clearwas for resetting things (Counters, Histograms). I tried to call it in my test suite so I could always start with a known, simple state (0).(And I thought it was a bug in prometheus_client that it raised an exception - until I read this ticket)
I thought maybe I should just make a new Histogram to replace the Histogram I had wanted to clear ... but nope, that's a collision in the registry.
So ... it would be nice if there were a way to reset everything to 0 for testing purposes. Right now I'm calling the private
_metric_initwhich seems to work for Histogram but I dunno about the other types.Clear is for clearing a labelset, so it should bug out here but probably it needs a better error message.
If you treat having no labels as a degenerate case, then it would make sense for it to not error out here.
I understand the point about not setting
Counterback to0in particular, but if you have a fixed-ish set of label values (perhaps 'successandfailure), you probably have exactly the same issue with.clear()` currently.So ... it would be nice if there were a way to reset everything to 0 for testing purposes.
Yes I think this is sensible, probably should be private or it will confuse people because of the mantra about "counters only go up".
If you treat having no labels as a degenerate case, then it would make sense for it to not error out here.
I think I agree since clear is not private.
Yes I think this is sensible, probably should be private or it will confuse people because of the mantra about "counters only go up".
I would recommend adding a
testingnamespace somewhere (egprometheus_client.testing) and placing such things there, with otherwise public names (egprometheus_client.testing.reset_counter). This avoids the confusion of the typical private convention (If it is private, am I intended to use it outside of prometheus_client? Usually the answer would be no.) but still makes it quite clear that if you use this API outside of testing then you're doing something wrong (and this message can be augmented with good docstrings on thetestingmodule/package and the individual APIs themselves).Reacted by Makarov Andrey and Jonathan MackenzieI do agree that this should not error in the without labels case. It might just not do anything which is fine as the counter would already be cleared.
I do actually think it could make sense to set the value to 0 though. This would be effectively forcing a counter reset which Prometheus would handle similar to if the process was restarted. It would also be the same as if you cleared all the labels then re-added one as that would start at 0 again.
Use case:
I have a metric deployment{name="my-deployment"} that is either 1 or 0, depending on the state.
If the deployment goes away the deployment metric will be stale. I need to clear them out so no stale metrics are left.
This works just fine from the REPL.
>>> import prometheus_client >>> gauge=prometheus_client.Gauge("test","Test Gauage",["name"]) >>> gauge.clear() >>>Redesigned the solution to be a pure wsgi application instead of some hybrid.
from prometheus_client import Gauge, make_wsgi_app, CollectorRegistry, genera import kwrapi app = make_wsgi_app() @app.route("/metrics") def metrics(): registry = CollectorRegistry() gauges = { "availableReplicas": Gauge("replicas_available", "Replicas availa "readyReplicas": Gauge("replicas_ready", "Replicas ready", ["name "updatedReplicas": Gauge("replicas_updated", "Updated replicas", "replicas": Gauge("replicas", "Replicas", ["name"], registry=regi } deployments = [] with kwrapi.session() as session: request = kwrapi.get_deployments() response = session.send(request) deployments.extend(response.json().get("items", [])) for deployment in deployments: metadata = deployment["metadata"] status = deployment.get("status", {}) for key, gauge in gauges.items(): _ = status.get(key) if _ is not None: gauge.labels(name=metadata["name"]).set(_) response = generate_latest(registry).decode() return response ~
Addendum. I had to use the flask Application instead because the WSGI implementation required a predefined registry as input. I wanted to generate a new one for each call.
After reading the rest of this thread, I'm aligning the fix with the direction discussed here rather than my original proposal. csmarchbanks, roidelapluie, sdfordham, and tomprince converged on treating a label-less metric as a degenerate case for clear() — since there's no labelset to clear, it should be a silent no-op rather than raising. That's different from remove()/remove_by_labels(), which intentionally raise because removing a specific (nonexistent) labelset is a more meaningful error case.
So the fix is:def clear(self) -> None:
"""Remove all labelsets from the metric"""
if not self._labelnames:
return
...I'll have a PR up shortly with this plus a regression test.
- added a commit that references this issue
on Jun 23, 2026 - added a commit that references this issue
on Jun 24, 2026
To reproduce:
The error returned is:
Is using .clear() in this way supported?