apache/kafka · error · IllegalArgumentException

For '{templateName}', runtime-defined metric tags do not mat

Error message

For '{templateName}', runtime-defined metric tags do not match the tags in the template. Runtime = {runtimeTagKeys} Template = {templateTagKeys}

What it means

Thrown by Metrics.metricInstance when the runtime tag key set supplied to instantiate a MetricNameTemplate does not exactly equal the template's declared tag key set. Templates exist to enforce uniform metric tag schemas across the codebase; metricInstance compares runtime keys (merged with the global MetricConfig.tags()) against template.tags() and rejects any drift (missing or extra keys).

Source

Thrown at clients/src/main/java/org/apache/kafka/common/metrics/Metrics.java:677

    /* For testing use only. */
    Map<Sensor, List<Sensor>> childrenSensors() {
        return Collections.unmodifiableMap(childrenSensors);
    }

    public MetricName metricInstance(MetricNameTemplate template, String... keyValue) {
        return metricInstance(template, MetricsUtils.getTags(keyValue));
    }

    public MetricName metricInstance(MetricNameTemplate template, Map<String, String> tags) {
        // check to make sure that the runtime defined tags contain all the template tags.
        Set<String> runtimeTagKeys = new HashSet<>(tags.keySet());
        runtimeTagKeys.addAll(config().tags().keySet());
        
        Set<String> templateTagKeys = template.tags();
        
        if (!runtimeTagKeys.equals(templateTagKeys)) {
            throw new IllegalArgumentException("For '" + template.name() + "', runtime-defined metric tags do not match the tags in the template. "
                    + "Runtime = " + runtimeTagKeys + " Template = " + templateTagKeys.toString());
        }
                
        return this.metricName(template.name(), template.group(), template.description(), tags);
    }

    /**
     * Close this metrics repository.
     */
    @Override
    public void close() {
        if (this.metricsScheduler != null) {
            this.metricsScheduler.shutdown();
            try {
                this.metricsScheduler.awaitTermination(30, TimeUnit.SECONDS);
            } catch (InterruptedException ex) {
                // ignore and continue shutdown
                Thread.currentThread().interrupt();

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Read the error message: it lists Runtime = {...} and Template = {...}; add the missing keys and remove the extras from your metricInstance call.
  2. If the template is what should change, update MetricNameTemplate's tags to match the desired schema and audit every call site.
  3. Keep template tag schemas in a single constants class and have callers reference the same keys to avoid drift.
  4. If a tag should be applied globally to every metric, put it in MetricConfig.tags() rather than passing it per-call.

Example fix

// before: MetricName n = metrics.metricInstance(template, "client-id", clientId);  // template expects {node-id}
// after:  MetricName n = metrics.metricInstance(template, "node-id", nodeId);
Defensive patterns

Strategy: validation

Validate before calling

// Build the exact tag set the template expects, then call metricInstance.
Set<String> expected = template.tags();
Map<String,String> tags = new LinkedHashMap<>();
for (String k : expected) tags.put(k, resolveValue(k));
// merge with MetricConfig-level tags to compare apples-to-apples
Set<String> runtime = new HashSet<>(tags.keySet());
runtime.addAll(metrics.config().tags().keySet());
if (!runtime.equals(expected)) {
    throw new IllegalArgumentException("Tag mismatch for " + template.name() + ": runtime=" + runtime + " template=" + expected);
}
metrics.metricInstance(template, tags);

Type guard

// Narrow to tag-set-equality before invoking metricInstance.
boolean tagsMatchTemplate(Metrics metrics, MetricNameTemplate t, Map<String,String> tags) {
    Set<String> runtime = new HashSet<>(tags.keySet());
    runtime.addAll(metrics.config().tags().keySet());
    return runtime.equals(t.tags());
}

Try / catch

try {
    MetricName mn = metrics.metricInstance(template, tags);
} catch (IllegalArgumentException e) {
    // recompute tag set from template.tags() and retry once.
}

Prevention

When it happens

Trigger: Calling metrics.metricInstance(template, "k1", "v1", "k2", "v2") where the template declares a different key set (e.g. {k1,k3}). The check at Metrics.java:676 throws IllegalArgumentException listing both the runtime and template key sets so the mismatch is visible.

Common situations: Adding a new tag to a MetricNameTemplate but forgetting to update every call site that builds a metric from it (or vice versa). Removing a tag from the template while leaving legacy callers passing it. Relying on MetricConfig.tags() to supply some keys but then changing which keys are global vs per-call. Refactoring metric tag schemas across versions without updating all producers of that metric.

Related errors


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