nathanmarz/storm · critical · RuntimeException

Could not instantiate a class listed in config under section

Error message

Could not instantiate a class listed in config under section ${Config.TOPOLOGY_METRICS_CONSUMER_REGISTER} with fully qualified name ${_consumerClassName}

What it means

During MetricsConsumerBolt.prepare, Storm reflectively instantiates each class registered under Config.TOPOLOGY_METRICS_CONSUMER_REGISTER via Class.forName(...).newInstance() and casts it to IMetricsConsumer. This RuntimeException wraps any failure in that process: the class name is wrong, the class is not on the worker's classpath, it lacks a no-arg constructor, is abstract/an interface, or its constructor/initialization throws. Because it fires in bolt prepare, the topology's system-metrics bolt fails to start.

Solutions

  1. Verify the 'class' entry in Config.TOPOLOGY_METRICS_CONSUMER_REGISTER is the exact fully-qualified class name (correct package, correct case).
  2. Ensure the class (and its dependencies) are bundled in the topology jar on the worker classpath.
  3. Give the consumer a public no-arg constructor and make it concrete (non-abstract) and implement backtype.storm.metric.IMetricsConsumer.
  4. Instantiate the class manually in a test (new MyConsumer()) to surface the wrapped cause 'e' in the stack trace and fix that root issue.

Example fix

// before
topology.metrics.consumer.register:
  - class: "com.example.MetricConsumer"   // typo, class is com.example.MetricsConsumer
// after
topology.metrics.consumer.register:
  - class: "com.example.MetricsConsumer"
Defensive patterns

Strategy: validation

Validate before calling

String cls = (String) consumerConf.get("class");
try {
    Class<?> c = Class.forName(cls);
    if (!backtype.storm.metric.IMetricsConsumer.class.isAssignableFrom(c))
        throw new IllegalArgumentException(cls + " does not implement IMetricsConsumer");
    c.getDeclaredConstructor().setAccessible(true); // fails here if no no-arg ctor
    c.newInstance();
} catch (Exception e) {
    throw new IllegalStateException("metrics consumer class not loadable/instantiable: " + cls, e);
}

Prevention

When it happens

Trigger: Class.forName fails (typo in 'class' field, class not in topology jar/worker classpath), newInstance fails (no public no-arg constructor, abstract class, constructor throws), or the instantiated object is not castable to IMetricsConsumer.

Common situations: Typo or wrong fully-qualified name in topology.metrics.consumer.register; custom IMetricsConsumer implementation missing from the submitted jar; class was refactored/renamed across Storm versions (e.g. backtype.storm vs org.apache.storm packages) leaving stale config; implementing class has only a constructor with arguments.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/fb2e7f962e92cd0c. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/backtype/storm/metric/MetricsConsumerBolt.java:46

import java.util.Map;

public class MetricsConsumerBolt implements IBolt {
    IMetricsConsumer _metricsConsumer;
    String _consumerClassName;
    OutputCollector _collector;
    Object _registrationArgument;

    public MetricsConsumerBolt(String consumerClassName, Object registrationArgument) {
        _consumerClassName = consumerClassName;
        _registrationArgument = registrationArgument;
    }

    @Override
    public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
        try {
            _metricsConsumer = (IMetricsConsumer)Class.forName(_consumerClassName).newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Could not instantiate a class listed in config under section " +
                Config.TOPOLOGY_METRICS_CONSUMER_REGISTER + " with fully qualified name " + _consumerClassName, e);
        }
        _metricsConsumer.prepare(stormConf, _registrationArgument, context, (IErrorReporter)collector);
        _collector = collector;
    }
    
    @Override
    public void execute(Tuple input) {
        _metricsConsumer.handleDataPoints((IMetricsConsumer.TaskInfo)input.getValue(0), (Collection)input.getValue(1));
        _collector.ack(input);
    }

    @Override
    public void cleanup() {
        _metricsConsumer.cleanup();
    }
    
}

View on GitHub (pinned to cdb116e942)