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

  1. Make the metric name unique by adding distinguishing tags (e.g. client-id, task-id, partition) when constructing the CompoundStat's NamedMeasurable names.
  2. Ensure the prior sensor is removed via Metrics.removeSensor(...) and that its metrics are deregistered before re-adding.
  3. Check sensor metrics()/registry for the name before adding, or guard registration with metrics.containsKey(name).
  4. 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

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


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/d9f90628e56660df.json. Report an issue: GitHub.