apache/hadoop · error · MetricsException

Error setting field {} annotated with {}

Error message

Error setting field {} annotated with {}

What it means

After building the MutableMetric for an @Metric-annotated field, MetricsSourceBuilder injects it with field.set(source, mutable). Any reflection failure at that assignment — most commonly a final field the builder cannot overwrite, or access blocked by security/module restrictions — is wrapped in MetricsException('Error setting field <field> annotated with <annotation>').

Source

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

        continue;
      }
      try {
        // skip fields already set
        field.setAccessible(true);
        if (field.get(source) != null) continue;
      } catch (Exception e) {
        LOG.warn("Error accessing field "+ field +" annotated with"+
                 annotation, e);
        continue;
      }
      MutableMetric mutable = factory.newForField(field, (Metric) annotation,
                                                  registry);
      if (mutable != null) {
        try {
          field.set(source, mutable); // Set the source field to MutableMetric
          hasAtMetric = true;
        } catch (Exception e) {
          throw new MetricsException("Error setting field "+ field +
                                     " annotated with "+ annotation, e);
        }
      }
    }
  }

  /** Add {@link MutableMetric} for a method annotated with {@link Metric} */
  private void add(Object source, Method method) {
    for (Annotation annotation : method.getAnnotations()) {
      if (!(annotation instanceof Metric)) {
        continue;
      }
      factory.newForMethod(source, method, (Metric) annotation, registry);
      hasAtMetric = true;
    }
  }
}

View on GitHub (pinned to 2add963021)

Solutions

  1. Remove final from @Metric-annotated fields so the builder can assign them
  2. Leave the field uninitialized (the builder creates and injects the MutableMetric)
  3. Ensure the class is reflectively accessible from the metrics2 code path (no security-manager denial)

Example fix

// before
@Metric
public final MutableGaugeLong size;

// after
@Metric
public MutableGaugeLong size;
Defensive patterns

Strategy: validation

Validate before calling

for (Field f : cls.getDeclaredFields()) {
  if (f.isAnnotationPresent(Metric.class) && Modifier.isFinal(f.getModifiers())) {
    throw new IllegalStateException("@Metric field must not be final: " + f);
  }
}

Type guard

static boolean isInjectableMetricField(Field f) {
  return f.isAnnotationPresent(Metric.class)
      && !Modifier.isFinal(f.getModifiers())
      && !Modifier.isStatic(f.getModifiers());
}

Prevention

When it happens

Trigger: Declaring @Metric on a final field (the builder must assign the MutableMetric into it), or on a field whose reflective write is disallowed in the runtime environment.

Common situations: Style habit of marking injected fields final; annotated fields that the developer also initializes themselves; restrictive security managers or module access rules around reflection.

Related errors


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