apache/hadoop · error · MetricsException

No valid @Metric annotation found.

Error message

No valid @Metric annotation found.

What it means

MetricsSourceBuilder.build() throws MetricsException('No valid @Metric annotation found.') when the object neither implements MetricsSource nor produced any usable @Metric member during the scan — the builder has nothing to build a metrics source from (hasAtMetric stayed false).

Source

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

    registry = initRegistry(source);

    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {
      add(source, field);
    }
    for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) {
      add(source, method);
    }
  }

  public MetricsSource build() {
    if (source instanceof MetricsSource) {
      if (hasAtMetric && !hasRegistry) {
        throw new MetricsException("Hybrid metrics: registry required.");
      }
      return (MetricsSource) source;
    }
    else if (!hasAtMetric) {
      throw new MetricsException("No valid @Metric annotation found.");
    }
    return new MetricsSource() {
      @Override
      public void getMetrics(MetricsCollector builder, boolean all) {
        registry.snapshot(builder.addRecord(registry.info()), all);
      }
    };
  }

  public MetricsInfo info() {
    return info;
  }

  private MetricsRegistry initRegistry(Object source) {
    Class<?> cls = source.getClass();
    MetricsRegistry r = null;
    // Get the registry if it already exists.
    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Annotate instance fields or methods with org.apache.hadoop.metrics2.annotation.Metric
  2. Or implement MetricsSource.getMetrics for a fully custom source
  3. Verify the annotated members are instance members of supported types (they must be wireable)

Example fix

// before
class MyMetrics { public long getSize() { return size; } }
new MetricsSourceBuilder(new MyMetrics(), "MyMetrics").build();  // throws

// after
class MyMetrics {
  @Metric public MutableGaugeLong size;
}
new MetricsSourceBuilder(new MyMetrics(), "MyMetrics").build();
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasValidMetricAnnotation(Class<?> cls) {
  boolean onFields = Arrays.stream(cls.getDeclaredFields())
      .anyMatch(f -> f.isAnnotationPresent(Metric.class));
  boolean onMethods = Arrays.stream(cls.getDeclaredMethods())
      .anyMatch(m -> m.isAnnotationPresent(Metric.class));
  return onFields || onMethods || MetricsSource.class.isAssignableFrom(cls);
}
if (!hasValidMetricAnnotation(cls)) throw new IllegalArgumentException(cls + " has no @Metric members");

Prevention

When it happens

Trigger: Passing a plain class with no @Metric-annotated fields or methods; or a class whose @Metric members were all rejected earlier in the scan (unsupported types), so none of them set hasAtMetric.

Common situations: Refactors that removed annotations; @Metric imported from the wrong package; annotations only on static members that the scan skips or fails to wire.

Related errors


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