{"record":{"id":"c44115d15ec8f48c","repo":"pentaho/pentaho-kettle","slug":"unexpected-error-loading-class-with-name-classname","errorCode":null,"errorMessage":"Unexpected error loading class with name: ${className}","messagePattern":"Unexpected error loading class with name: (.+?)","errorType":"exception","errorClass":"KettlePluginException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java","lineNumber":883,"sourceCode":"            } else {\n              ucl = folderBasedClassLoaderMap.get( plugin.getPluginDirectory().toString() );\n            }\n          }\n          if ( ucl != null ) {\n            classLoaders.put( plugin, ucl ); // save for later use...\n          }\n        } finally {\n          lock.writeLock().unlock();\n        }\n\n        if ( ucl == null ) {\n          throw new KettlePluginException( \"Unable to find class loader for plugin: \" + plugin );\n        }\n        return (T) ucl.loadClass( className );\n\n      }\n    } catch ( Exception e ) {\n      throw new KettlePluginException( \"Unexpected error loading class with name: \" + className, e );\n    }\n  }\n\n  /**\n   * Load the class with a certain name using the class loader of certain plugin.\n   *\n   * @param plugin    The plugin for which we want to use the class loader\n   * @param classType The type of class to load\n   * @return the name of the class\n   * @throws KettlePluginException In case there is something wrong\n   */\n  @SuppressWarnings( \"unchecked\" )\n  public <T> T getClass( PluginInterface plugin, T classType ) throws KettlePluginException {\n    String className = plugin.getClassMap().get( classType );\n    return (T) getClass( plugin, className );\n  }\n\n  /**","sourceCodeStart":865,"sourceCodeEnd":901,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/plugins/PluginRegistry.java#L865-L901","documentation":"Generic wrapper thrown at the end of the registry's loadClass(PluginInterface, String): any Exception raised inside the method (ClassNotFound from ucl.loadClass, the class-loader errors above, security exceptions) is rethrown as 'Unexpected error loading class with name: <className>' with the original as cause. It signals that resolving or loading the plugin's class failed for an unclassified reason.","triggerScenarios":"Calling PluginRegistry.loadClass(PluginInterface, String className) where the class name is wrong/absent from the plugin jar, the plugin's class loader is missing (errors 311/312), or Class.forName on a native plugin fails; the inner exception is wrapped and rethrown here.","commonSituations":"See trigger scenarios.","solutions":["Read the chained cause to distinguish ClassNotFoundException (fix class name/jar) from the class-loader errors (fix plugin registration).","Confirm the fully-qualified class name matches the compiled class inside the plugin jar (javap -cp plugin.jar ... or unzip -l).","Ensure the plugin folder/jars are deployed and scanned by the registry at startup.","Update plugin.xml/@Step annotation class attributes after package or class renames."],"exampleFix":"// before\n@Step(id = \"MyStep\", name = \"My Step\", classNmae = \"com.acme.MyStepp\")\n// after\n@Step(id = \"MyStep\", name = \"My Step\", className = \"com.acme.MyStep\")","handlingStrategy":"try-catch","validationCode":"String cls = className == null ? plugin.getMainClass() : className;\nif (cls == null || cls.isEmpty()) throw new IllegalArgumentException(\"No class name for plugin \" + plugin);\n// confirm class presence in the plugin's loader\ntry { PluginRegistry.getInstance().getClassLoader(plugin).loadClass(cls); } catch (ClassNotFoundException e) { /* resolve before real call */ }","typeGuard":"boolean pluginClassExists(PluginInterface plugin, String className) {\n  try {\n    ClassLoader cl = PluginRegistry.getInstance().getClassLoader(plugin);\n    cl.loadClass(className);\n    return true;\n  } catch (Exception e) { return false; }\n}","tryCatchPattern":"try {\n  T obj = PluginRegistry.getInstance().loadClass(plugin, className, MyInterface.class);\n} catch (KettlePluginException e) {\n  Throwable cause = e.getCause(); // ClassNotFoundException vs loader-missing\n  LOG.error(\"loadClass failed for \" + className + \": \" + cause, e);\n  throw new PluginDeploymentException(className, e);\n}","preventionTips":["Keep @Step/@JobEntry annotation class attributes in sync with refactored class names.","Verify fully-qualified names with unzip -l / javap before shipping a plugin.","Never swallow the cause chain — log e.getCause() to tell 'wrong class name' from 'missing loader'."],"tags":["plugin-loading","class-not-found","reflection","kettle"],"backgroundTag":"class-not-found","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}