apache/iceberg · error · IllegalArgumentException
Cannot initialize MetricsReporter, %s does not implement Met
Error message
Cannot initialize MetricsReporter, %s does not implement MetricsReporter.
What it means
CatalogUtil.loadMetricsReporter instantiates the configured class and relies on the DynConstructors-built factory's generic cast to detect type errors. If the instantiated object does not actually implement MetricsReporter, newInstance() throws ClassCastException, which is converted to an IllegalArgumentException stating the class does not implement MetricsReporter. This guards the property-configured reporter type at load time.
Source
Thrown at core/src/main/java/org/apache/iceberg/CatalogUtil.java:539
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;
}
public static String fullTableName(String catalogName, TableIdentifier identifier) {
StringBuilder sb = new StringBuilder();
if (catalogName.contains("/") || catalogName.contains(":")) {
// use / for URI-like names: thrift://host:port/db.table
sb.append(catalogName);
if (!catalogName.endsWith("/")) {
sb.append("/");View on GitHub (pinned to 86d9c8fc54)
Solutions
- Verify the configured class implements org.apache.iceberg.metrics.MetricsReporter and add `implements MetricsReporter` if missing.
- Check the metrics-impl property value for typos or copy-paste of the wrong fully qualified class name.
- Ensure a single, non-shaded copy of iceberg-core (and its MetricsReporter interface) is on the classpath so the instanceof check matches.
- Rebuild/redeploy the reporter class against the Iceberg version in use.
Example fix
// before
public class MyReporter implements io.micrometer.core.instrument.reporter.MetricsReporter { ... }
// after
import org.apache.iceberg.metrics.MetricsReporter;
public class MyReporter implements MetricsReporter {
@Override public void initialize(Map<String, String> properties) { ... }
@Override public void report(MetricsReport report) { ... }
} Defensive patterns
Strategy: type-guard
Validate before calling
Class<?> reporterClass = Class.forName(metricsImplClass, false, CatalogUtil.class.getClassLoader());
if (!org.apache.iceberg.metrics.MetricsReporter.class.isAssignableFrom(reporterClass)) {
throw new IllegalStateException(metricsImplClass + " does not implement MetricsReporter");
} Type guard
boolean isMetricsReporter(String className, ClassLoader cl) {
try {
return org.apache.iceberg.metrics.MetricsReporter.class
.isAssignableFrom(Class.forName(className, false, cl));
} catch (ClassNotFoundException e) { return false; }
} Try / catch
try {
MetricsReporter r = CatalogUtil.loadMetricsReporter(impl, properties);
} catch (IllegalArgumentException e) {
if (e.getCause() instanceof ClassCastException) {
// wrong class configured for metrics-impl; verify with isAssignableFrom before retrying
}
throw e;
} Prevention
- Double-check fully qualified class names in metrics-impl configuration.
- Compile reporter classes against the same iceberg-core version on the runtime classpath.
- Avoid shading iceberg-core so the MetricsReporter interface identity is unique.
When it happens
Trigger: Setting metrics-impl / metrics-reporter-impl to a class that is instantiable but does not implement org.apache.iceberg.metrics.MetricsReporter — e.g. a typo pointing to the wrong class or an unrelated class in the same package.
Common situations: Configured class implements a similarly named reporter interface from a different library or an older iceberg API; copy-paste of the impl string from another config; the class implements MetricsReporter from a shaded/duplicate copy of the iceberg API in a different classloader.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Cannot initialize LockManager, %s does not implement LockMan
- Cannot initialize AliyunClientFactory, %s does not implement
- Cannot initialize AdlsTokenCredentialProvider, %s does not i
- Cannot initialize Catalog, %s does not implement Catalog.
- Cannot initialize FileIO, %s does not implement FileIO.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/0b4cda6ae1493bff.
Report an issue: GitHub.