pentaho/pentaho-kettle · error · KettleException
ScriptMeta.Exception.UnableToParseXMLforAdditionalClasses
Error message
ScriptMeta.Exception.UnableToParseXMLforAdditionalClasses
What it means
This ScriptMeta constructor parses 'additional classes' (Java classes shipped with jars to be exposed to the JavaScript step) from XML, then loads each jar/class via LoadAdditionalClass from the plugin path. Any failure reading the XML or instantiating the class is wrapped in KettleException 'UnableToParseXMLforAdditionalClasses'.
Solutions
- Verify the jar named in the step XML exists under plugins/steps/ScriptValues_mod/ on this machine.
- Check the class name spelling and that the jar actually contains it (jar tf).
- Ensure the JVM version can load the class (compile target compatible with runtime JDK).
- Inspect the nested cause to distinguish XML parsing vs class loading vs instantiation failure.
Example fix
// before: step references missing jar in XML <strJarName>MyHelper.jar</strJarName> // jar absent on this node // after: deploy the jar cp MyHelper.jar $PENTHO/plugins/steps/ScriptValues_mod/
Defensive patterns
Strategy: validation
Validate before calling
// Verify jar and plugin dir before loading the transformation
File jar = new File("plugins/steps/ScriptValues_mod/MyHelper.jar");
if (!jar.isFile()) throw new IllegalStateException("missing jar: " + jar); Try / catch
try { loadTransformation(); } catch (KettleException e) {
if (e.getMessage().contains("UnableToParseXMLforAdditionalClasses")) {
// inspect cause: XML parse vs jar missing vs newInstance
}
} Prevention
- Deploy all referenced plugin jars to every node
- Use fully qualified class names in step XML
- Keep JVM version compatible with jar targets
- Diff step XML against a known-good transformation
When it happens
Trigger: Loading a transformation whose Script step declares additional class entries, when strJarName/strClassName XML tags are malformed, the plugin path 'plugins/steps/ScriptValues_mod/' + jar is missing, or addClass.newInstance() fails.
Common situations: Transformation moved between machines where the extra jar isn't installed in the plugin directory; jar compiled for a different Java version; typo in class name in the step XML.
Related errors
- ERROR_0016_COULD_NOT_GET_REPOSITORY_INSTANCE
- ScriptMeta.Exception.UnableToLoadAdditionalClass
- ScriptValuesMetaMod.Exception.UnableToParseXMLforAdditionalC…
- CloneRowMeta.Exception.UnableToReadStepInfo
- ColumnExistsMeta.Exception.UnableToReadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/4311e86be1f62121.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/script/ScriptMeta.java:826
Document dom = XMLHandler.loadXMLFile( DefaultBowl.getInstance(),
strActPath + "/plugins/steps/ScriptValues_mod/plugin.xml" );
Node stepnode = dom.getDocumentElement();
Node libraries = XMLHandler.getSubNode( stepnode, "js_libraries" );
int nbOfLibs = XMLHandler.countNodes( libraries, "js_lib" );
additionalClasses = new ScriptAddClasses[nbOfLibs];
for ( int i = 0; i < nbOfLibs; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( libraries, "js_lib", i );
String strJarName = XMLHandler.getTagAttribute( fnode, "name" );
String strClassName = XMLHandler.getTagAttribute( fnode, "classname" );
String strJSName = XMLHandler.getTagAttribute( fnode, "js_name" );
Class<?> addClass =
LoadAdditionalClass( strActPath + "/plugins/steps/ScriptValues_mod/" + strJarName, strClassName );
Object addObject = addClass.newInstance();
additionalClasses[i] = new ScriptAddClasses( addClass, addObject, strJSName );
}
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString(
PKG, "ScriptMeta.Exception.UnableToParseXMLforAdditionalClasses" ), e );
}
}
private static Class<?> LoadAdditionalClass( String strJar, String strClassName ) throws KettleException {
try {
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
URL u = new URL( "jar:file:" + strJar + "!/" );
// We never know what else the script wants to load with the class loader, so lets not close it just like that.
@SuppressWarnings( "resource" )
KettleURLClassLoader kl = new KettleURLClassLoader( new URL[] { u }, cl );
Class<?> toRun = kl.loadClass( strClassName );
return toRun;
} catch ( Exception e ) {
throw new KettleException(
BaseMessages.getString( PKG, "ScriptMeta.Exception.UnableToLoadAdditionalClass" ), e );
}View on GitHub (pinned to f3058517a1)