apache/kafka · error · IllegalArgumentException
A metric named '{metricName}' already exists, can't register
Error message
A metric named '{metricName}' already exists, can't register another one. What it means
Thrown by Sensor.add(CompoundStat stat, MetricConfig config) when registry.registerMetric returns a non-null existing metric for one of the NamedMeasurable produced by the compound stat. The global Metrics registry keys metrics by MetricName (group+name+tags), so a collision means two different stats are trying to publish the same metric identity. It surfaces as an IllegalArgumentException to prevent silent overwriting of an existing KafkaMetric.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/metrics/Sensor.java:304
* Register a compound statistic with this sensor which yields multiple measurable quantities (like a histogram)
* @param stat The stat to register
* @param config The configuration for this stat. If null then the stat will use the default configuration for this
* sensor.
* @return true if stat is added to sensor, false if sensor is expired
*/
public synchronized boolean add(CompoundStat stat, MetricConfig config) {
if (hasExpired())
return false;
final MetricConfig statConfig = config == null ? this.config : config;
stats.add(new StatAndConfig(Objects.requireNonNull(stat), () -> statConfig));
Object lock = metricLock();
for (NamedMeasurable m : stat.stats()) {
final KafkaMetric metric = new KafkaMetric(lock, m.name(), m.stat(), statConfig, time);
if (!metrics.containsKey(metric.metricName())) {
KafkaMetric existingMetric = registry.registerMetric(metric);
if (existingMetric != null) {
throw new IllegalArgumentException("A metric named '" + metric.metricName() + "' already exists, can't register another one.");
}
metrics.put(metric.metricName(), metric);
}
}
return true;
}
/**
* Register a metric with this sensor
* @param metricName The name of the metric
* @param stat The statistic to keep
* @return true if metric is added to sensor, false if sensor is expired
*/
public boolean add(MetricName metricName, MeasurableStat stat) {
return add(metricName, stat, null);
}
/**View on GitHub (pinned to c31c9215e1)
Solutions
- Make the metric name unique by adding distinguishing tags (e.g. client-id, task-id, partition) when constructing the CompoundStat's NamedMeasurable names.
- Ensure the prior sensor is removed via Metrics.removeSensor(...) and that its metrics are deregistered before re-adding.
- Check sensor metrics()/registry for the name before adding, or guard registration with metrics.containsKey(name).
- Use a dedicated Metrics instance (or PluginMetrics scope) per component so unrelated metrics cannot collide on the same name.
Example fix
// before
Sensor s = metrics.sensor("latency");
s.add(new Percentiles(100, Percentiles.BUCKET_100_LATENCIES));
// re-run: name "latency-percentiles" already registered -> exception
// after
Sensor s = metrics.sensor("latency-" + taskId);
s.add(new Percentiles(100, Percentiles.BUCKET_100_LATENCIES));
// unique per task; or metrics.removeSensor("latency") before re-adding Defensive patterns
Strategy: try-catch
Try / catch
try {
sensor.add(compoundStat, config);
} catch (IllegalArgumentException e) {
// one of this CompoundStat's NamedMeasurables collides with an existing metric name
log.warn("Skipping compound stat {} — metric already registered", compoundStat, e);
} Prevention
- Use globally-unique metric names derived from a stable namespace prefix.
- Register each CompoundStat's measurables once at startup, not per request or per connection.
- Avoid adding the same CompoundStat type to multiple sensors that share a Metrics registry.
When it happens
Trigger: Calling sensor.add(compoundStat) (e.g. a Histogram, Percentiles, or any CompoundStat emitting multiple NamedMeasurables) where at least one of stat.stats() yields a MetricName already registered in the same Metrics instance. Common when two sensors add the same compound stat type with identical name/tags, or when a sensor is recreated after the prior metric was not removed.
Common situations: Plugin or connector code that registers a Histogram/Percentiles per task without including a unique tag (task id, partition) in the metric name; re-registration after a restart where the previous sensor's metric lingers; shared Metrics instance across components that happen to pick the same metric name; tests reusing a static Metrics without cleanup.
Related errors
- A metric named '{metricName}' already exists, can't register
- Circular dependency in sensors: {name} is its own parent.
- Metric {metricName} already exists
- Telemetry is not enabled. Set config `enable.metrics.push` t
- Error creating mbean attribute for metricName :{metricName}
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/d9f90628e56660df.json.
Report an issue: GitHub.