{"id":"dbf5ffd0d81950c6","repo":"apache/kafka","slug":"metric-metricname-already-exists","errorCode":null,"errorMessage":"Metric {metricName} already exists","messagePattern":"Metric (.+?) already exists","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/internals/PluginMetricsImpl.java","lineNumber":64,"sourceCode":"\n    @Override\n    public MetricName metricName(String name, String description, LinkedHashMap<String, String> tags) {\n        if (closing) throw new IllegalStateException(\"This PluginMetrics instance is closed\");\n        for (String tagName : tags.keySet()) {\n            if (this.tags.containsKey(tagName)) {\n                throw new IllegalArgumentException(\"Cannot use \" + tagName + \" as a tag name\");\n            }\n        }\n        Map<String, String> metricsTags = new LinkedHashMap<>(this.tags);\n        metricsTags.putAll(tags);\n        return metrics.metricName(name, GROUP, description, metricsTags);\n    }\n\n    @Override\n    public void addMetric(MetricName metricName, MetricValueProvider<?> metricValueProvider) {\n        if (closing) throw new IllegalStateException(\"This PluginMetrics instance is closed\");\n        if (metricNames.contains(metricName)) {\n            throw new IllegalArgumentException(\"Metric \" + metricName + \" already exists\");\n        }\n        metrics.addMetric(metricName, metricValueProvider);\n        metricNames.add(metricName);\n    }\n\n    @Override\n    public void removeMetric(MetricName metricName) {\n        if (closing) throw new IllegalStateException(\"This PluginMetrics instance is closed\");\n        if (metricNames.contains(metricName)) {\n            metrics.removeMetric(metricName);\n            metricNames.remove(metricName);\n        } else {\n            throw new IllegalArgumentException(\"Unknown metric \" + metricName);\n        }\n    }\n\n    @Override\n    public Sensor addSensor(String name) {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/internals/PluginMetricsImpl.java#L46-L82","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npluginMetrics.addMetric(name, provider); // first task\npluginMetrics.addMetric(name, provider); // second task -> throws\n\n// after\nMetricName perTask = pluginMetrics.metricName(\"rx\", \"d\",\n    new LinkedHashMap<>(Map.of(\"task-id\", String.valueOf(taskId))));\npluginMetrics.addMetric(perTask, provider);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    pluginMetrics.addMetric(metricName, provider);\n} catch (IllegalArgumentException e) {\n    // metric already registered (e.g. on re-init or duplicate setup); treat as idempotent\n    log.debug(\"Metric {} already registered, skipping\", metricName, e);\n}","preventionTips":["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."],"tags":["metrics","plugin","duplicate-registration","metric-name"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}