{"record":{"id":"08226d1e6462f378","repo":"pentaho/pentaho-kettle","slug":"scriptvaluesmetamod-exception-08226d","errorCode":null,"errorMessage":"ScriptValuesMetaMod.Exception.UnableToParseXMLforAdditionalClasses","messagePattern":"ScriptValuesMetaMod\\.Exception\\.UnableToParseXMLforAdditionalClasses","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesMetaMod.java","lineNumber":990,"sourceCode":"      Document dom = XMLHandler.loadXMLFile( DefaultBowl.getInstance(),\n                                             strActPath + \"/plugins/steps/ScriptValues_mod/plugin.xml\" );\n      Node stepnode = dom.getDocumentElement();\n      Node libraries = XMLHandler.getSubNode( stepnode, \"js_libraries\" );\n      int nbOfLibs = XMLHandler.countNodes( libraries, \"js_lib\" );\n      additionalClasses = new ScriptValuesAddClasses[nbOfLibs];\n      for ( int i = 0; i < nbOfLibs; i++ ) {\n        Node fnode = XMLHandler.getSubNodeByNr( libraries, \"js_lib\", i );\n        String strJarName = XMLHandler.getTagAttribute( fnode, \"name\" );\n        String strClassName = XMLHandler.getTagAttribute( fnode, \"classname\" );\n        String strJSName = XMLHandler.getTagAttribute( fnode, \"js_name\" );\n\n        Class<?> addClass =\n          LoadAdditionalClass( strActPath + \"/plugins/steps/ScriptValues_mod/\" + strJarName, strClassName );\n        Object addObject = addClass.newInstance();\n        additionalClasses[i] = new ScriptValuesAddClasses( addClass, addObject, strJSName );\n      }\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    }","sourceCodeStart":972,"sourceCodeEnd":1008,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/scriptvalues_mod/ScriptValuesMetaMod.java#L972-L1008","documentation":"When building a ScriptValuesMod step from XML (constructor that reads additional script classes), any exception while loading the configured additional JARs/classes is wrapped in a KettleException with this message. It indicates the <add_classes> section of the step XML could not be turned into live additionalClasses objects. The root cause is attached.","triggerScenarios":"During XML deserialization of step metadata: the configured class path '<kettle-home>/plugins/steps/ScriptValues_mod/<jar>' does not exist or is unreadable, the JAR is corrupt, the class name is wrong/missing, Class.newInstance() fails (no public no-arg ctor, or constructor throws), or the XML structure is malformed.","commonSituations":"Transformation XML moved to a machine where the extra JAR was not deployed under plugins/steps/ScriptValues_mod/; typo in the additional class name; the additional class was compiled against a different JDK or its no-arg constructor changed; plugin folder renamed.","solutions":["Read the nested cause to identify the exact failure (FileNotFound vs ClassNotFoundException vs InstantiationError)","Deploy the referenced additional JAR to <kettle-dir>/plugins/steps/ScriptValues_mod/ and verify strActPath resolves to the real Kettle home","Check the class name stored in the step XML matches a class actually present in the JAR","Ensure the additional class has a public no-argument constructor that does not throw","Re-export the transformation XML after fixing the additional-classes configuration"],"exampleFix":"// before: class missing on this machine -> wrapped as UnableToParseXMLforAdditionalClasses\n// <add_classes><jar>myhelper.jar</jar><class>com.x.Helper</class>...\n// after: verify before loading\nFile jar = new File(strActPath + \"/plugins/steps/ScriptValues_mod/myhelper.jar\");\nif (!jar.exists()) throw new KettleException(\"Deploy myhelper.jar to \" + jar.getPath());","handlingStrategy":"validation","validationCode":"File dir = new File(System.getProperty(\"KETTLE_HOME\", \".\"), \"plugins/steps/ScriptValues_mod\");\nfor (String jar : configuredJars) {\n  if (!new File(dir, jar).exists())\n    throw new KettleException(\"Missing additional jar: \" + jar + \" in \" + dir);\n}","typeGuard":null,"tryCatchPattern":"try {\n  stepMeta = new StepMeta(xStepNode, transMeta);\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"UnableToParseXMLforAdditionalClasses\")) {\n    logError(\"Additional classes load failed: \" + e.getCause(), e);\n    // deploy JARs and retry, or strip add_classes from the XML\n  } else throw e;\n}","preventionTips":["Deploy all additional JARs to every environment under plugins/steps/ScriptValues_mod/","Prefer built-in scripting capabilities over custom additional classes to reduce deploy coupling","Keep additional classes with public no-arg constructors and no side effects in them","Pin JDK version used to compile additional JARs to the runtime JDK or lower","Validate exported transformation XML with a smoke-load before promoting it"],"tags":["xml","classloading","plugin","kettle","deserialization"],"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"}