apache/iceberg · error · IllegalArgumentException
Cannot initialize MetricsReporter, missing no-arg…
Error message
Cannot initialize MetricsReporter, missing no-arg constructor: %s
What it means
CatalogUtil.loadMetricsReporter instantiates a MetricsReporter implementation reflectively via DynConstructors requiring a public no-arg constructor. If no such constructor exists, an IllegalArgumentException is thrown saying the reporter is missing a no-arg constructor. Metrics reporters must be instantiable without arguments because they are configured entirely through the initialize(Map) call with table properties.
Solutions
- Add a public no-arg constructor to the MetricsReporter implementation.
- Move constructor dependencies into the initialize(Map<String, String> properties) method, reading them from catalog/table properties.
- Point the metrics-impl property at a different class that has a public no-arg constructor.
- Verify the constructor is public and takes zero parameters (not inherited or narrowed visibility).
Example fix
// before
public class MyReporter implements MetricsReporter {
private final String registry;
public MyReporter(String registry) { this.registry = registry; }
}
// after
public class MyReporter implements MetricsReporter {
private String registry;
public MyReporter() {}
@Override
public void initialize(Map<String, String> properties) {
this.registry = properties.get("metrics.registry");
}
} Defensive patterns
Strategy: validation
Validate before calling
Class<?> reporterClass = Class.forName(metricsImplClass, false, CatalogUtil.class.getClassLoader());
java.lang.reflect.Constructor<?> noArg =
java.util.Arrays.stream(reporterClass.getConstructors())
.filter(c -> c.getParameterCount() == 0)
.findFirst()
.orElseThrow(() -> new IllegalStateException(
metricsImplClass + " has no public no-arg constructor")); Type guard
boolean hasNoArgConstructor(String className) {
try {
Class<?> c = Class.forName(className, false, Thread.currentThread().getContextClassLoader());
return java.util.Arrays.stream(c.getConstructors())
.anyMatch(k -> k.getParameterCount() == 0);
} catch (ClassNotFoundException e) { return false; }
} Try / catch
try {
MetricsReporter r = CatalogUtil.loadMetricsReporter(impl, properties);
} catch (IllegalArgumentException e) {
// fall back to default LoggingMetricsReporter and surface the bad config
MetricsReporter r = new LoggingMetricsReporter();
r.initialize(properties);
} Prevention
- Always give MetricsReporter implementations a public no-arg constructor.
- Pass configuration through initialize(properties) rather than constructor arguments.
- Unit-test your reporter class instantiation via its configured impl string.
When it happens
Trigger: Setting the metrics-impl property (or metrics-reporter-impl on a table) to a class that only defines parameterized constructors, e.g. new MyReporter(Factory) with no public MyReporter().
Common situations: Writing a custom reporter that takes constructor dependencies instead of configuring via initialize(); a reporter designed for programmatic use being wired in via config; constructor declared package-private or private instead of public.
Related errors
- Cannot bind constructors
- Cannot find constructor for
- Cannot initialize AwsClientFactory, missing no-arg…
- Cannot initialize DellClientFactory, missing no-arg…
- Cannot initialize MetricsReporter
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3e9a141d9b15e959.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/CatalogUtil.java:530
* @throws IllegalArgumentException if class path not found or right constructor not found or the
* loaded class cannot be cast to the given interface type
*/
public static MetricsReporter loadMetricsReporter(Map<String, String> properties) {
String impl = properties.get(CatalogProperties.METRICS_REPORTER_IMPL);
if (impl == null) {
return LoggingMetricsReporter.instance();
}
LOG.info("Loading custom MetricsReporter implementation: {}", impl);
DynConstructors.Ctor<MetricsReporter> ctor;
try {
ctor =
DynConstructors.builder(MetricsReporter.class)
.loader(CatalogUtil.class.getClassLoader())
.impl(impl)
.buildChecked();
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
String.format("Cannot initialize MetricsReporter, missing no-arg constructor: %s", impl),
e);
}
MetricsReporter reporter;
try {
reporter = ctor.newInstance();
} catch (ClassCastException e) {
throw new IllegalArgumentException(
String.format(
"Cannot initialize MetricsReporter, %s does not implement MetricsReporter.", impl),
e);
}
reporter.initialize(properties);
return reporter;
}View on GitHub (pinned to 86d9c8fc54)