{"record":{"id":"3e9a141d9b15e959","repo":"apache/iceberg","slug":"cannot-initialize-metricsreporter-missing-no-arg","errorCode":null,"errorMessage":"Cannot initialize MetricsReporter, missing no-arg constructor: %s","messagePattern":"Cannot initialize MetricsReporter, missing no-arg constructor: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/CatalogUtil.java","lineNumber":530,"sourceCode":"   * @throws IllegalArgumentException if class path not found or right constructor not found or the\n   *     loaded class cannot be cast to the given interface type\n   */\n  public static MetricsReporter loadMetricsReporter(Map<String, String> properties) {\n    String impl = properties.get(CatalogProperties.METRICS_REPORTER_IMPL);\n    if (impl == null) {\n      return LoggingMetricsReporter.instance();\n    }\n\n    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  }","sourceCodeStart":512,"sourceCodeEnd":548,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/CatalogUtil.java#L512-L548","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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)."],"exampleFix":"// before\npublic class MyReporter implements MetricsReporter {\n  private final String registry;\n  public MyReporter(String registry) { this.registry = registry; }\n}\n\n// after\npublic class MyReporter implements MetricsReporter {\n  private String registry;\n  public MyReporter() {}\n  @Override\n  public void initialize(Map<String, String> properties) {\n    this.registry = properties.get(\"metrics.registry\");\n  }\n}","handlingStrategy":"validation","validationCode":"Class<?> reporterClass = Class.forName(metricsImplClass, false, CatalogUtil.class.getClassLoader());\njava.lang.reflect.Constructor<?> noArg =\n    java.util.Arrays.stream(reporterClass.getConstructors())\n        .filter(c -> c.getParameterCount() == 0)\n        .findFirst()\n        .orElseThrow(() -> new IllegalStateException(\n            metricsImplClass + \" has no public no-arg constructor\"));","typeGuard":"boolean hasNoArgConstructor(String className) {\n  try {\n    Class<?> c = Class.forName(className, false, Thread.currentThread().getContextClassLoader());\n    return java.util.Arrays.stream(c.getConstructors())\n        .anyMatch(k -> k.getParameterCount() == 0);\n  } catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n  MetricsReporter r = CatalogUtil.loadMetricsReporter(impl, properties);\n} catch (IllegalArgumentException e) {\n  // fall back to default LoggingMetricsReporter and surface the bad config\n  MetricsReporter r = new LoggingMetricsReporter();\n  r.initialize(properties);\n}","preventionTips":["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."],"tags":["reflection","constructor","metrics","invalid-config-value"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}