{"record":{"id":"31359915ca8833cd","repo":"apache/iceberg","slug":"failed-to-load-configuration-after-loading-configu","errorCode":null,"errorMessage":"Failed to load Configuration after loading Configurable","messagePattern":"Failed to load Configuration after loading Configurable","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/CatalogUtil.java","lineNumber":478,"sourceCode":"      return;\n    }\n\n    if (!configurableInterface.isInstance(maybeConfigurable)) {\n      // not Configurable because the object does not implement the Configurable interface\n      return;\n    }\n\n    Class<?> configurationClass;\n    try {\n      configurationClass =\n          DynClasses.builder()\n              .loader(maybeConfigurableLoader)\n              .impl(\"org.apache.hadoop.conf.Configuration\")\n              .buildChecked();\n    } catch (ClassNotFoundException e) {\n      // this shouldn't happen because Configurable cannot be loaded without first loading\n      // Configuration\n      throw new UnsupportedOperationException(\n          \"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","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/CatalogUtil.java#L460-L496","documentation":"CatalogUtil.configureHadoopConf loads the Hadoop Configuration class reflectively after successfully loading a Configurable (a Catalog or FileIO). If Configuration itself cannot be loaded via the same classloader, this UnsupportedOperationException is thrown. The code comments note this 'shouldn't happen' because a Configurable cannot be loaded without first loading Configuration, so it indicates a corrupted or inconsistent classloader state.","triggerScenarios":"Calling CatalogUtil.loadCatalog(...) or loadFileIO(...) with a custom classloader where the Configurable class loads but org.apache.hadoop.conf.Configuration does not resolve via DynClasses; or a classloader whose parent delegation is broken/filtered (shaded environments, exotic plugin classloaders).","commonSituations":"Hadoop jars are shaded/relocated or absent from the runtime classpath but a stub Configurable class is present; custom plugin classloaders that hide org.apache.hadoop packages; mismatched classloader hierarchies in Flink/Spark/Hive metastore plugin setups.","solutions":["Verify Hadoop's configuration classes are on the classpath of the same classloader that loads the catalog/FileIO implementation.","Inspect any custom classloader passed via ClassLoader and ensure it delegates to the parent for org.apache.hadoop.* classes.","Check for shading/relocation of org.apache.hadoop.conf.Configuration in a fat jar and un-relocate it or add the real hadoop-common dependency.","Align Hadoop versions so the Configuration class is loadable by CatalogUtil's configured loader (catalog.loader.impl / catalog.classloader properties)."],"exampleFix":"// before (broken: custom classloader filters hadoop classes)\nCatalogUtil.loadCatalog(\"org.apache.iceberg.hive.HiveCatalog\", \"hive\", null, myIsolatingClassLoader);\n\n// after (fix classloader delegation or use default loader)\nCatalogUtil.loadCatalog(\"org.apache.iceberg.hive.HiveCatalog\", \"hive\", null,\n    Thread.currentThread().getContextClassLoader());","handlingStrategy":"try-catch","validationCode":"ClassLoader cl = pluginClassLoader;\nClass<?> conf = Class.forName(\"org.apache.hadoop.conf.Configuration\", true, cl);\nif (conf == null) { throw new IllegalStateException(\"Hadoop Configuration not loadable by plugin classloader\"); }","typeGuard":"boolean hasHadoopConf(ClassLoader cl) {\n  try { Class.forName(\"org.apache.hadoop.conf.Configuration\", false, cl); return true; }\n  catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n  CatalogUtil.loadCatalog(impl, name, properties, conf);\n} catch (UnsupportedOperationException e) {\n  if (e.getCause() instanceof ClassNotFoundException) {\n    // fall back to default classloader or fail fast with a clear setup error\n  }\n  throw e;\n}","preventionTips":["Ensure hadoop-common is a provided/compile dependency in plugin deployments.","Avoid custom classloaders that exclude org.apache.hadoop.* from parent delegation.","Test catalog loading in the exact shaded fat-jar environment you ship."],"tags":["classloader","hadoop","reflection","configuration"],"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-14T11:17:12.474Z"}