{"record":{"id":"379a102d0d4765f8","repo":"apache/iceberg","slug":"failed-to-load-configuration-setconf-after-loading","errorCode":null,"errorMessage":"Failed to load Configuration.setConf after loading Configurable","messagePattern":"Failed to load Configuration\\.setConf after loading Configurable","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/CatalogUtil.java","lineNumber":497,"sourceCode":"          \"Failed to load Configuration after loading Configurable\", e);\n    }\n\n    ValidationException.check(\n        configurationClass.isInstance(conf),\n        \"%s is not an instance of Configuration from the classloader for %s\",\n        conf,\n        maybeConfigurable);\n\n    DynMethods.BoundMethod setConf;\n    try {\n      setConf =\n          DynMethods.builder(\"setConf\")\n              .impl(configurableInterface, configurationClass)\n              .buildChecked()\n              .bind(maybeConfigurable);\n    } catch (NoSuchMethodException e) {\n      // this shouldn't happen because Configurable was loaded and defines setConf\n      throw new UnsupportedOperationException(\n          \"Failed to load Configuration.setConf after loading Configurable\", e);\n    }\n\n    setConf.invoke(conf);\n  }\n\n  /**\n   * Load a custom {@link MetricsReporter} implementation.\n   *\n   * <p>The implementation must have a no-arg constructor.\n   *\n   * @param properties catalog properties which contains class name of a custom {@link\n   *     MetricsReporter} implementation\n   * @return An initialized {@link MetricsReporter}.\n   * @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) {","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/CatalogUtil.java#L479-L515","documentation":"After loading a Configurable and its Hadoop Configuration class, configureHadoopConf reflectively looks up the setConf(Configuration) method and binds it to the instance. If setConf cannot be found on the loaded Configurable, this UnsupportedOperationException is thrown. It is an internal-invariant error: any class implementing Configurable must define setConf, so this signals an unexpectedly malformed or mismatched class.","triggerScenarios":"CatalogUtil.loadCatalog or loadFileIO receives a class whose Configurable interface was loaded from a different classloader than the instance's own classloader, so DynMethods cannot resolve setConf(Configuration) with the Configuration class argument; or the class implements a relocated/shaded Configurable variant.","commonSituations":"Shading that relocates org.apache.hadoop.conf.Configurable on one side but not the other; mixed Hadoop versions on the classpath; custom classloaders loading duplicate copies of Configurable/Configuration.","solutions":["Ensure only one copy of org.apache.hadoop.conf.Configurable exists on the classpath (no duplicate/relocated hadoop jars).","Make sure the same classloader loads the implementation, Configurable, and Configuration classes.","Check shade plugin excludes so hadoop configuration classes are not relocated in plugin jars.","Align hadoop-common versions between the application and the catalog/FileIO plugin."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"Class<?> implClass = Class.forName(implName, true, loader);\nif (!org.apache.hadoop.conf.Configurable.class.isAssignableFrom(implClass)) {\n  throw new IllegalStateException(\"implementation is not a Hadoop Configurable\");\n}","typeGuard":"boolean definesSetConf(Class<?> c, ClassLoader cl) {\n  try {\n    Class<?> conf = Class.forName(\"org.apache.hadoop.conf.Configuration\", false, cl);\n    return java.lang.reflect.Modifier.isPublic(c.getModifiers())\n        && java.util.Arrays.stream(c.getMethods())\n            .anyMatch(m -> m.getName().equals(\"setConf\")\n                && m.getParameterCount() == 1 && m.getParameterTypes()[0] == conf);\n  } catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n  CatalogUtil.loadFileIO(fileIOImpl, properties, hadoopConf);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"setConf\")) {\n    // duplicated/relocated Configurable classes — log classloader sources before rethrowing\n  }\n  throw e;\n}","preventionTips":["Keep exactly one copy of org.apache.hadoop classes on the classpath.","Do not relocate hadoop classes in shaded plugin jars.","Pin one hadoop-common version across the application and plugins."],"tags":["classloader","hadoop","reflection","method-not-found"],"backgroundTag":"class-not-found","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"}