pentaho/pentaho-kettle · error · KettleXMLException
JobPGPDecryptFiles.Error.Exception.UnableLoadXML
Error message
JobPGPDecryptFiles.Error.Exception.UnableLoadXML
What it means
Thrown by JobEntryPGPDecryptFiles.loadXML when parsing the job entry's XML definition raises a KettleXMLException. The original XML parse exception is wrapped and identified with a localized message so callers know the PGP decrypt entry could not be deserialized.
Solutions
- Open the .kjb file in Spoon to identify the malformed entry and repair or recreate it.
- Validate the job XML against the expected JobEntryPGPDecryptFiles element structure (nodes with passphrase, destination_filefolder, wildcard, etc.).
- Restore the job file from backup or source control.
- Inspect getCause() (the wrapped KettleXMLException) for the exact parse error and line.
Example fix
// before: hand-edited XML with missing closing tag on <wildcard> // after: regenerate the entry XML via Spoon, or repair: // <wildcard>.*\.pgp</wildcard> // ensure every file node contains passphrase, destination_filefolder and wildcard elements
Defensive patterns
Strategy: try-catch
Validate before calling
// validate job XML before loading
Document doc = XMLHandler.loadXMLFile( jobFile );
if ( doc == null || XMLHandler.getSubNode( doc, "job" ) == null ) {
throw new IllegalArgumentException( "Not a valid Kettle job XML" );
} Try / catch
try {
jobEntry.loadXML( entryNode, databases, slaveServers, rep, metaStore );
} catch ( KettleXMLException e ) {
logError( "PGP decrypt entry XML is corrupt; restore from backup. Cause: " + e.getCause(), e );
} Prevention
- Don't hand-edit .kjb files; edit in Spoon.
- Keep job files in source control for recovery.
- Use consistent Pentaho versions between designer and runtime.
- Verify file integrity after transfers.
When it happens
Trigger: loadXML(entryNode, ...) reads attributes via XMLHandler.getTagValue on each node; if the XML is malformed, a required node/element is absent in a way XMLHandler rejects, or getNodes fails, KettleXMLException is caught and re-wrapped.
Common situations: Corrupt or hand-edited .kjb job file; XML exported from a newer/older Pentaho version with changed element structure; truncated file transfer; wrong node passed in by custom code.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- ColumnExistsMeta.Exception.UnableToReadStepInfo
- CreditCardValidatorMeta.Exception.UnableToReadStepInfo
- CubeOutputMeta.Exception.UnableToLoadStepInfo
- DelayMeta.Exception.UnableToReadStepInfo
- DynamicSQLRowMeta.Exception.UnableToLoadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/47561bfc53e6806e.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/entries/pgpdecryptfiles/JobEntryPGPDecryptFiles.java:264
Node fields = XMLHandler.getSubNode( entrynode, "fields" );
// How many field arguments?
int nrFields = XMLHandler.countNodes( fields, "field" );
allocate( nrFields );
// Read them all...
for ( int i = 0; i < nrFields; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( fields, "field", i );
source_filefolder[i] = XMLHandler.getTagValue( fnode, "source_filefolder" );
passphrase[i] = Encr.decryptPasswordOptionallyEncrypted( XMLHandler.getTagValue( fnode, "passphrase" ) );
destination_filefolder[i] = XMLHandler.getTagValue( fnode, "destination_filefolder" );
wildcard[i] = XMLHandler.getTagValue( fnode, "wildcard" );
}
} catch ( KettleXMLException xe ) {
throw new KettleXMLException( BaseMessages.getString(
PKG, "JobPGPDecryptFiles.Error.Exception.UnableLoadXML" ), xe );
}
}
public void loadRep( Repository rep, IMetaStore metaStore, ObjectId id_jobentry, List<DatabaseMeta> databases,
List<SlaveServer> slaveServers ) throws KettleException {
try {
gpglocation = rep.getJobEntryAttributeString( id_jobentry, "gpglocation" );
arg_from_previous = rep.getJobEntryAttributeBoolean( id_jobentry, "arg_from_previous" );
include_subfolders = rep.getJobEntryAttributeBoolean( id_jobentry, "include_subfolders" );
add_result_filesname = rep.getJobEntryAttributeBoolean( id_jobentry, "add_result_filesname" );
destination_is_a_file = rep.getJobEntryAttributeBoolean( id_jobentry, "destination_is_a_file" );
create_destination_folder = rep.getJobEntryAttributeBoolean( id_jobentry, "create_destination_folder" );
nr_errors_less_than = rep.getJobEntryAttributeString( id_jobentry, "nr_errors_less_than" );
success_condition = rep.getJobEntryAttributeString( id_jobentry, "success_condition" );
add_date = rep.getJobEntryAttributeBoolean( id_jobentry, "add_date" );
add_time = rep.getJobEntryAttributeBoolean( id_jobentry, "add_time" );
SpecifyFormat = rep.getJobEntryAttributeBoolean( id_jobentry, "SpecifyFormat" );View on GitHub (pinned to f3058517a1)