{"record":{"id":"03c688488579bc01","repo":"pentaho/pentaho-kettle","slug":"scriptvaluesmetamod-exception-unabletoloadadditionalclass","errorCode":null,"errorMessage":"ScriptValuesMetaMod.Exception.UnableToLoadAdditionalClass","messagePattern":"ScriptValuesMetaMod\\.Exception\\.UnableToLoadAdditionalClass","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesMetaMod.java","lineNumber":1006,"sourceCode":"      }\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString(\n        PKG, \"ScriptValuesMetaMod.Exception.UnableToParseXMLforAdditionalClasses\" ), e );\n    }\n  }\n\n  private static Class<?> LoadAdditionalClass( String strJar, String strClassName ) throws KettleException {\n    try {\n      Thread t = Thread.currentThread();\n      ClassLoader cl = t.getContextClassLoader();\n      URL u = new URL( \"jar:file:\" + strJar + \"!/\" );\n      // We never know what else the script wants to load with the class loader, so lets not close it just like that.\n      @SuppressWarnings( \"resource\" )\n      KettleURLClassLoader kl = new KettleURLClassLoader( new URL[] { u }, cl );\n      Class<?> toRun = kl.loadClass( strClassName );\n      return toRun;\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString(\n        PKG, \"ScriptValuesMetaMod.Exception.UnableToLoadAdditionalClass\" ), e );\n    }\n  }\n\n  public ScriptValuesAddClasses[] getAddClasses() {\n    return additionalClasses;\n  }\n\n  /**\n   * @return the compatible\n   */\n  public boolean isCompatible() {\n    return compatible;\n  }\n\n  /**\n   * @param compatible\n   *          the compatible to set","sourceCodeStart":988,"sourceCodeEnd":1024,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesMetaMod.java#L988-L1024","documentation":"LoadAdditionalClass wraps any failure to load a class from an additional ScriptValues_mod JAR with a KettleURLClassLoader into a KettleException with this message. It is the lower-level cause of the additional-classes load failure: the JAR URL could not be opened or loadClass could not find/define the requested class. The root cause is attached.","triggerScenarios":"new URL(jarPath) fails or the JAR file does not exist/is unreadable; kl.loadClass(strClassName) throws ClassNotFoundException because the class is absent from the JAR or the class name is misspelled; JAR is corrupt or compiled for an incompatible class file version; linkage errors (NoClassDefFoundError/LinkageError) for missing transitive dependencies.","commonSituations":"Typo in class name in the step configuration; JAR built with a newer JDK than the runtime; additional class references libraries not on the classpath (transitive dependency missing); JAR not deployed on a cluster node.","solutions":["Read the nested cause: ClassNotFoundException -> fix class name/deploy JAR; UnsupportedClassVersionError -> rebuild or run a newer JDK","Verify the class name (fully qualified, no typo, correct case) configured for the additional class","Ensure the JAR exists and is readable at the given path and is a valid ZIP/JAR (unzip -t)","Bundle or add to the classpath any libraries the additional class depends on","Deploy identical JARs to every node (clustered execution)"],"exampleFix":"// before\nClass<?> toRun = kl.loadClass(\"com.x.Helperr\"); // ClassNotFoundException\n// after: check before wrapping the jar\nFile f = new File(jarPath);\nif (!f.canRead()) throw new KettleException(\"Missing additional jar: \" + jarPath);\nClass<?> toRun = kl.loadClass(\"com.x.Helper\"); // exact FQN","handlingStrategy":"try-catch","validationCode":"try (JarFile jf = new JarFile(jarPath)) {\n  if (jf.getJarEntry(className.replace('.', '/') + \".class\") == null)\n    throw new KettleException(\"Class \" + className + \" not in \" + jarPath);\n}","typeGuard":null,"tryCatchPattern":"try {\n  Class<?> c = new KettleURLClassLoader(new URL[]{ new URL(jarPath) }, cl).loadClass(className);\n} catch (ClassNotFoundException cnfe) {\n  throw new KettleException(\"Class \" + className + \" not found in \" + jarPath\n    + \" — check FQN spelling and JAR deployment\", cnfe);\n} catch (IOException ioe) {\n  throw new KettleException(\"Cannot open JAR \" + jarPath, ioe);\n}","preventionTips":["Use fully qualified, case-correct class names in step configuration","Verify JAR integrity (unzip -t) after copying between environments","Match the compile-time target JDK to the runtime JDK","Ship transitive dependencies inside the additional JAR or on the plugin classpath","Deploy identical JAR sets to all cluster nodes"],"tags":["classloading","classloader","jar","kettle","plugin"],"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"}