apache/hadoop · error · MetricsException

Unexpected metrics type {} for {}

Error message

Unexpected metrics type {} for {}

What it means

MetricsRegistry.newRate(name, desc, extended, returnExisting=true) is the get-or-create path for rate metrics: an existing registration under that name is returned only if it is a MutableRate. If the name maps to a different MutableMetric subclass (counter, gauge, quantiles), it throws MetricsException('Unexpected metrics type <class> for <name>').

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/lib/MetricsRegistry.java:321

  /**
   * Create a mutable rate metric (for throughput measurement).
   * @param name  of the metric
   * @param desc  description
   * @param extended  produce extended stat (stdev/min/max etc.) if true
   * @return a new mutable rate metric object
   */
  public MutableRate newRate(String name, String desc, boolean extended) {
    return newRate(name, desc, extended, true);
  }

  @InterfaceAudience.Private
  public synchronized MutableRate newRate(String name, String desc,
      boolean extended, boolean returnExisting) {
    if (returnExisting) {
      MutableMetric rate = metricsMap.get(name);
      if (rate != null) {
        if (rate instanceof MutableRate) return (MutableRate) rate;
        throw new MetricsException("Unexpected metrics type "+ rate.getClass()
                                   +" for "+ name);
      }
    }
    checkMetricName(name);
    MutableRate ret = new MutableRate(name, desc, extended);
    metricsMap.put(name, ret);
    return ret;
  }

  public synchronized MutableRatesWithAggregation newRatesWithAggregation(
      String name) {
    checkMetricName(name);
    MutableRatesWithAggregation rates = new MutableRatesWithAggregation();
    metricsMap.put(name, rates);
    return rates;
  }

  public synchronized MutableRollingAverages newMutableRollingAverages(

View on GitHub (pinned to 2add963021)

Solutions

  1. Rename one of the two metrics so each name has one type within the registry
  2. If a rate is intended, remove the earlier counter/gauge/quantiles registration of that name
  3. Audit the annotated class or registry for duplicate metric names and give them distinct names

Example fix

// before
registry.newCounter("ProcTime", "Processing time");
registry.newRate("ProcTime", "Processing time", true);  // throws

// after
registry.newCounter("ProcTimeCount", "Processing count");
registry.newRate("ProcTime", "Processing time", true);
Defensive patterns

Strategy: validation

Validate before calling

Map<String, Class<?>> registered = new ConcurrentHashMap<>();
// record every registration: registered.put("Foo", MutableRate.class);
Class<?> existing = registered.get("Foo");
if (existing == null || existing == MutableRate.class) {
  registry.newRate("Foo", "desc", true);
}

Try / catch

try {
  registry.newRate("Foo", "desc", true);
} catch (MetricsException e) {
  // "Unexpected metrics type" => name already claimed by a non-rate metric; rename
  registry.newRate("FooRate", "desc", true);
}

Prevention

When it happens

Trigger: Calling newRate("Foo", ..., true) after newCounter/newGauge/newQuantiles already registered a non-rate metric named "Foo" in the same registry.

Common situations: Name collisions inside one @Metrics-annotated class or registry — e.g., a MutableStat field and an implicit newRate sharing a name; refactors that changed a metric's type while the old declaration stayed.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/ce77d96228f58c46. Report an issue: GitHub.