apache/kafka · error · IllegalArgumentException
Metric {metricName} already exists
Error message
Metric {metricName} already exists What it means
Thrown by PluginMetricsImpl.addMetric when the given MetricName is already in the instance's metricNames set. PluginMetrics tracks each metric it owns so it can clean them up on close; registering the same MetricName twice is a programmer error. IllegalArgumentException surfaces the duplicate before the underlying Metrics.addMetric would also reject it.
Source
Thrown at clients/src/main/java/org/apache/kafka/common/metrics/internals/PluginMetricsImpl.java:64
@Override
public MetricName metricName(String name, String description, LinkedHashMap<String, String> tags) {
if (closing) throw new IllegalStateException("This PluginMetrics instance is closed");
for (String tagName : tags.keySet()) {
if (this.tags.containsKey(tagName)) {
throw new IllegalArgumentException("Cannot use " + tagName + " as a tag name");
}
}
Map<String, String> metricsTags = new LinkedHashMap<>(this.tags);
metricsTags.putAll(tags);
return metrics.metricName(name, GROUP, description, metricsTags);
}
@Override
public void addMetric(MetricName metricName, MetricValueProvider<?> metricValueProvider) {
if (closing) throw new IllegalStateException("This PluginMetrics instance is closed");
if (metricNames.contains(metricName)) {
throw new IllegalArgumentException("Metric " + metricName + " already exists");
}
metrics.addMetric(metricName, metricValueProvider);
metricNames.add(metricName);
}
@Override
public void removeMetric(MetricName metricName) {
if (closing) throw new IllegalStateException("This PluginMetrics instance is closed");
if (metricNames.contains(metricName)) {
metrics.removeMetric(metricName);
metricNames.remove(metricName);
} else {
throw new IllegalArgumentException("Unknown metric " + metricName);
}
}
@Override
public Sensor addSensor(String name) {View on GitHub (pinned to c31c9215e1)
Solutions
- Guard with metricNames.contains(metricName) (or a plugin-side Set) before calling addMetric, or use addMetric only once per logical metric.
- Add a distinguishing tag (task-id, partition, client-id) so each logical source has a unique MetricName.
- Call pluginMetrics.removeMetric(metricName) before re-adding, or restart the plugin's PluginMetrics instance to reset the set.
- Move addMetric to a single initialization point so it cannot be hit multiple times per lifecycle.
Example fix
// before
pluginMetrics.addMetric(name, provider); // first task
pluginMetrics.addMetric(name, provider); // second task -> throws
// after
MetricName perTask = pluginMetrics.metricName("rx", "d",
new LinkedHashMap<>(Map.of("task-id", String.valueOf(taskId))));
pluginMetrics.addMetric(perTask, provider); Defensive patterns
Strategy: try-catch
Try / catch
try {
pluginMetrics.addMetric(metricName, provider);
} catch (IllegalArgumentException e) {
// metric already registered (e.g. on re-init or duplicate setup); treat as idempotent
log.debug("Metric {} already registered, skipping", metricName, e);
} Prevention
- Register each plugin metric exactly once at init(); guard re-init paths.
- Make addMetric idempotent in your plugin wrapper so repeated setup is a no-op.
- Use stable, namespaced metric names so accidental re-registration collides safely.
When it happens
Trigger: Calling pluginMetrics.addMetric(metricName, provider) twice with an equal MetricName (same name, group="plugins", and tags). Equality is MetricName equality, so identical name+tags-grouped identity triggers the exception.
Common situations: Plugin init code that runs twice (e.g. idempotent re-init not guarded); per-task metric registration without a task-id tag so every task collides on the same MetricName; tests that reuse a PluginMetrics and forget to removeMetric between cases; refactors that moved addMetric into a loop without a contains check.
Related errors
- A metric named '{metricName}' already exists, can't register
- A metric named '{metricName}' already exists, can't register
- This PluginMetrics instance is closed
- Cannot use {tagName} as a tag name
- Telemetry is not enabled. Set config `enable.metrics.push` t
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/dbf5ffd0d81950c6.json.
Report an issue: GitHub.