pentaho/pentaho-kettle · error · KettleXMLException
Unable to load job entry of type 'shell' from XML node
Error message
Unable to load job entry of type 'shell' from XML node
What it means
JobEntryShell.loadXML parses the job entry's XML node into fields; any KettleException raised while reading tags is wrapped in KettleXMLException('Unable to load job entry of type 'shell' from XML node'). The message identifies which job entry type failed to deserialize, with the parse error as cause.
Solutions
- Open the .kjb in an XML editor and validate it is well-formed
- Compare the shell job entry node against a working one (check argument0..argumentN tags and argnr)
- Recreate the shell job entry in Spoon and re-save the job file
- Restore the file from version control/backup if it was truncated
Defensive patterns
Strategy: try-catch
Try / catch
try {
jobEntryShell.loadXML(entrynode, databases, metaStore);
} catch (KettleXMLException e) {
logError("Shell job entry XML invalid: " + e.getCause().getMessage(), e);
// fall back to re-creating the entry or loading a backup .kjb
} Prevention
- Do not hand-edit .kjb files; edit via Spoon
- Keep argument0..argumentN tags consistent with the argnr value
- Version-control job files so truncated edits can be reverted
- Validate XML after any external generation/templating of job files
When it happens
Trigger: XMLHandler.getTagValue calls throw (malformed XML document, null entrynode) while loading a 'shell' job entry from a .kjb file, including reading the repeated argument0..argumentN tags.
Common situations: Hand-edited or truncated .kjb files; XML saved by a newer/older Pentaho version with divergent tag layout; copy-paste of job entries losing attributes; invalid characters in arguments breaking XML escaping.
Related errors
- ERROR_0001
- JobDosToUnix.Error.Exception.UnableLoadXML
- JobEntryDeleteFolders.UnableToLoadFromXml
- JobEntryDeleteResultFilenames.CanNotLoadFromXML
- JobEntrySimple.Error.Exception.UnableLoadXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/72a6bfa620d6e9b9.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/shell/JobEntryShell.java:185
insertScript = "Y".equalsIgnoreCase( XMLHandler.getTagValue( entrynode, "insertScript" ) );
script = XMLHandler.getTagValue( entrynode, "script" );
// How many arguments?
int argnr = 0;
while ( XMLHandler.getTagValue( entrynode, "argument" + argnr ) != null ) {
argnr++;
}
allocate( argnr );
// Read them all...
// THIS IS A VERY BAD WAY OF READING/SAVING AS IT MAKES
// THE XML "DUBIOUS". DON'T REUSE IT.
for ( int a = 0; a < argnr; a++ ) {
arguments[a] = XMLHandler.getTagValue( entrynode, "argument" + a );
}
} catch ( KettleException e ) {
throw new KettleXMLException( "Unable to load job entry of type 'shell' from XML node", e );
}
}
// Load the jobentry from repository
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
setFileName( rep.getJobEntryAttributeString( id_jobentry, "file_name" ) );
setWorkDirectory( rep.getJobEntryAttributeString( id_jobentry, "work_directory" ) );
argFromPrevious = rep.getJobEntryAttributeBoolean( id_jobentry, "arg_from_previous" );
execPerRow = rep.getJobEntryAttributeBoolean( id_jobentry, "exec_per_row" );
setLogfile = rep.getJobEntryAttributeBoolean( id_jobentry, "set_logfile" );
setAppendLogfile = rep.getJobEntryAttributeBoolean( id_jobentry, "set_append_logfile" );
addDate = rep.getJobEntryAttributeBoolean( id_jobentry, "add_date" );
addTime = rep.getJobEntryAttributeBoolean( id_jobentry, "add_time" );
logfile = rep.getJobEntryAttributeString( id_jobentry, "logfile" );
logext = rep.getJobEntryAttributeString( id_jobentry, "logext" );View on GitHub (pinned to f3058517a1)