apache/seatunnel · warning
Name collision: MetricsContext already contains a Metric wit
Error message
Name collision: MetricsContext already contains a Metric with the name '{}'. Metric will not be reported. What it means
AbstractMetricsContext.addMetric detects a name collision when putting a Metric into the metrics map: if a Metric already exists under that name, the original metric is restored and the new one is discarded with a warning. Duplicate metric names mean one of the two metrics will never be reported.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/common/metrics/AbstractMetricsContext.java:69
}
return this.meter(name, new ThreadSafeQPSMeter(name));
}
@Override
public <M extends Meter> M meter(String name, M meter) {
this.addMetric(name, meter);
return meter;
}
protected void addMetric(String name, Metric metric) {
if (metric == null) {
log.warn("Ignoring attempted add of a metric due to being null for name {}.", name);
} else {
synchronized (this) {
Metric prior = this.metrics.put(name, metric);
if (prior != null) {
this.metrics.put(name, prior);
log.warn(
"Name collision: MetricsContext already contains a Metric with the name '"
+ name
+ "'. Metric will not be reported.");
}
}
}
}
@Override
public String toString() {
return "AbstractMetricsContext{" + "metrics=" + metrics + '}';
}
}
View on GitHub (pinned to cf67b549a7)
Solutions
- Uniquify metric names by including subtask/parallelism/table identifiers, e.g. name + "#" + subtaskIndex.
- Guard registration with a check that the name is not already present before calling counter()/meter().
- Move metric registration to one-time initialization (open/init) rather than per-record or per-retry paths.
- If re-registration is intended, remove the old metric first.
Example fix
// before
context.counter("records_received"); // collides on retry
context.counter("records_received");
// after
String name = "records_received#" + context.getIndexOfSubtask();
if (!metricsContext.contains(name)) {
context.counter(name);
} Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
if (!seen.add(metricName)) throw new IllegalStateException("duplicate metric name: " + metricName); Type guard
if (existingMetrics.containsKey(metricName)) { metricName = metricName + "#" + subtaskIndex; } Try / catch
// warning-only path; prevent duplicates rather than catching
Prevention
- Namespace metric names with subtask index / table / plugin id
- Register metrics once in open()/init()
- Grep plugin code for hard-coded metric name strings before reuse
- Review metric names during checkpoint/retry code paths
When it happens
Trigger: Calling counter(name)/meter(name)/addMetric(name, metric) twice with the same metric name within the same MetricsContext, e.g. re-registering metrics on task retry or across overlapping component lifecycles.
Common situations: Source/sink or transform plugins registering metrics with hard-coded names that collide across subtasks; checkpoint restart re-invoking initialization code; copy-pasted metric names within one pipeline.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Ignoring attempted add of a metric due to being null for nam
- Collect realtime metrics failed
- Metrics snapshots are updated through merge semantics rather
- Unsupported metric class: ${metricClass}
- The value of Metric does not support ${metricType} data type
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/c6b93463fc5c8f25.
Report an issue: GitHub.