{"record":{"id":"0b4cda6ae1493bff","repo":"apache/iceberg","slug":"cannot-initialize-metricsreporter-s-does-not-imp","errorCode":null,"errorMessage":"Cannot initialize MetricsReporter, %s does not implement MetricsReporter.","messagePattern":"Cannot initialize MetricsReporter, (.+?) does not implement MetricsReporter\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/CatalogUtil.java","lineNumber":539,"sourceCode":"    LOG.info(\"Loading custom MetricsReporter implementation: {}\", impl);\n    DynConstructors.Ctor<MetricsReporter> ctor;\n    try {\n      ctor =\n          DynConstructors.builder(MetricsReporter.class)\n              .loader(CatalogUtil.class.getClassLoader())\n              .impl(impl)\n              .buildChecked();\n    } catch (NoSuchMethodException e) {\n      throw new IllegalArgumentException(\n          String.format(\"Cannot initialize MetricsReporter, missing no-arg constructor: %s\", impl),\n          e);\n    }\n\n    MetricsReporter reporter;\n    try {\n      reporter = ctor.newInstance();\n    } catch (ClassCastException e) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Cannot initialize MetricsReporter, %s does not implement MetricsReporter.\", impl),\n          e);\n    }\n\n    reporter.initialize(properties);\n\n    return reporter;\n  }\n\n  public static String fullTableName(String catalogName, TableIdentifier identifier) {\n    StringBuilder sb = new StringBuilder();\n\n    if (catalogName.contains(\"/\") || catalogName.contains(\":\")) {\n      // use / for URI-like names: thrift://host:port/db.table\n      sb.append(catalogName);\n      if (!catalogName.endsWith(\"/\")) {\n        sb.append(\"/\");","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/CatalogUtil.java#L521-L557","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic class MyReporter implements io.micrometer.core.instrument.reporter.MetricsReporter { ... }\n\n// after\nimport org.apache.iceberg.metrics.MetricsReporter;\npublic class MyReporter implements MetricsReporter {\n  @Override public void initialize(Map<String, String> properties) { ... }\n  @Override public void report(MetricsReport report) { ... }\n}","handlingStrategy":"type-guard","validationCode":"Class<?> reporterClass = Class.forName(metricsImplClass, false, CatalogUtil.class.getClassLoader());\nif (!org.apache.iceberg.metrics.MetricsReporter.class.isAssignableFrom(reporterClass)) {\n  throw new IllegalStateException(metricsImplClass + \" does not implement MetricsReporter\");\n}","typeGuard":"boolean isMetricsReporter(String className, ClassLoader cl) {\n  try {\n    return org.apache.iceberg.metrics.MetricsReporter.class\n        .isAssignableFrom(Class.forName(className, false, cl));\n  } catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n  MetricsReporter r = CatalogUtil.loadMetricsReporter(impl, properties);\n} catch (IllegalArgumentException e) {\n  if (e.getCause() instanceof ClassCastException) {\n    // wrong class configured for metrics-impl; verify with isAssignableFrom before retrying\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["type-mismatch","metrics","reflection","config"],"backgroundTag":"incompatible-source-type","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}