apache/hadoop · error · MetricsConfigException

Error creating plugin: {}

Error message

Error creating plugin: {}

What it means

MetricsConfig.getPlugin reflectively instantiates every metrics2 source/sink/filter named by a *.class property in hadoop-metrics2.properties: Class.forName with the plugin classloader, newInstance(), then plugin.init(subsetConfig). Any failure — class not found, no accessible no-arg constructor, ClassCastException to MetricsPlugin, or an exception thrown inside init() — is wrapped in MetricsConfigException('Error creating plugin: <className>') with the original cause attached. It surfaces during MetricsSystem init, typically at daemon startup or first metrics use.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/metrics2/impl/MetricsConfig.java:210

                                     : PREFIX_DEFAULT + key);
    }
    LOG.debug("Returning '{}' for key: {}", value, key);
    return value;
  }

  <T extends MetricsPlugin> T getPlugin(String name) {
    String clsName = getClassName(name);
    if (clsName == null) {
      return null;
    }
    try {
      Class<?> cls = Class.forName(clsName, true, getPluginLoader());
      @SuppressWarnings("unchecked")
      T plugin = (T) cls.newInstance();
      plugin.init(name.isEmpty() ? this : subset(name));
      return plugin;
    } catch (Exception e) {
      throw new MetricsConfigException("Error creating plugin: "+ clsName, e);
    }
  }

  String getClassName(String prefix) {
    String classKey = prefix.isEmpty() ? "class" : prefix.concat(".class");
    String clsName = getString(classKey);
    LOG.debug("Class name for prefix {} is {}", prefix, clsName);
    if (clsName == null || clsName.isEmpty()) {
      return null;
    }
    return clsName;
  }

  ClassLoader getPluginLoader() {
    if (pluginLoader != null) {
      return pluginLoader;
    }
    final ClassLoader defaultLoader = getClass().getClassLoader();

View on GitHub (pinned to 2add963021)

Solutions

  1. Read the nested cause first (getCause()) — it distinguishes ClassNotFoundException vs InstantiationException vs init() failure and points at the real fix.
  2. Verify the class name spelling and that the jar is on the daemon's classpath (put it in HADOOP_COMMON_LIB_NATIVE or the service lib dir) with a public no-arg constructor implementing the right MetricsPlugin interface.
  3. Fix the plugin's own config subset (its sink/source properties) if the cause is an init() exception.
  4. As a stopgap, comment out the offending *.class property to restore metrics startup, then redeploy the fixed plugin.

Example fix

# before
*.sink.graph.class=com.example.GraphiteSink   # jar missing on nodes

# after
cp graphite-metrics-sink.jar $HADOOP_HOME/share/hadoop/common/lib/
# or, to restore startup immediately:
# *.sink.graph.class=org.apache.hadoop.metrics2.sink.FileSink
# *.sink.graph.filename=/tmp/metrics.out
Defensive patterns

Strategy: try-catch

Validate before calling

// Smoke-test a configured plugin class before trusting it in production
String clsName = metricsConf.getString("sink.custom.class");
Class<?> c = Class.forName(clsName, true, pluginClassLoader);
if (!org.apache.hadoop.metrics2.MetricsSink.class.isAssignableFrom(c)
    && !org.apache.hadoop.metrics2.MetricsSource.class.isAssignableFrom(c)) {
  throw new IllegalArgumentException(clsName + " implements neither MetricsSink nor MetricsSource");
}
c.getConstructor(); // fails fast without a public no-arg ctor

Try / catch

try {
  MetricsSource src = conf.getPlugin("source.custom");
} catch (MetricsConfigException mce) {
  Throwable root = mce.getCause() != null ? mce.getCause() : mce;
  LOG.error("metrics2 plugin failed to load: {} (cause: {})",
      mce.getMessage(), root.toString());
  // decide: fall back to a stock sink or abort startup with a clear message
}

Prevention

When it happens

Trigger: *.sink.custom.class=com.example.MySink where the jar is absent from the daemon classpath; class lacks a public no-arg constructor; class does not implement MetricsSink/MetricsSource; plugin.init() throws because its own config subset is incomplete (e.g., FileSink without a filename).

Common situations: Deploying custom metrics sinks (Graphite/Kafka/Prometheus writers) and forgetting the jar or shading it wrongly; typo in the class property; version upgrades renaming plugin classes; sink-specific properties missing after config migration.

Related errors


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