pentaho/pentaho-kettle · error · KettleXMLException
PGPDecryptStreamMeta.Exception.UnableToReadStepInfo
Error message
PGPDecryptStreamMeta.Exception.UnableToReadStepInfo
What it means
PGPDecryptStreamMeta.loadXML throws KettleXMLException when it cannot parse the step's XML definition into step metadata (passphrase, stream field, result field, passphrase-from-field settings). It wraps the underlying exception so callers know which step failed to load. Thrown from readData while reading the <stepnode> XML tags.
Solutions
- Open the .ktr in Spoon and re-save the PGP Decrypt Stream step to regenerate valid XML
- Validate the XML file is well-formed (xmllint or an XML editor)
- Compare the step's XML block against a working transformation and fix missing/renamed tags
- Check Pentaho/PDI version compatibility between the file and your runtime
Example fix
// before: hand-edited XML missing passphrase tag <passhrase></passphrase> // after: correct matching tag <passhrase>encrypted_value</passhrase>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate .ktr XML before loading
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
Document doc = f.newDocumentBuilder().parse(new File("trans.ktr"));
NodeList steps = doc.getElementsByTagName("step");
for (int i = 0; i < steps.getLength(); i++) {
Element s = (Element) steps.item(i);
if ("PGPDecryptStream".equals(s.getAttribute("type"))) {
if (s.getElementsByTagName("passhrase").getLength() == 0) {
throw new IllegalStateException("PGP step XML missing <passhrase> tag");
}
}
} Try / catch
try { transMeta.loadXML(file, null, null); }
catch (KettleXMLException e) {
if (e.getMessage().contains("UnableToReadStepInfo")) {
log.error("PGP decrypt step XML is malformed: " + e.getCause(), e);
} else { throw e; }
} Prevention
- Never hand-edit .ktr files; edit in Spoon
- Keep PDI versions consistent between authors and runners
- Version-control transformations and diff XML after edits
- Validate XML well-formedness before deployment
When it happens
Trigger: Loading a transformation (.ktr) whose PGP decrypt stream step XML contains malformed or unexpected content, or an XMLHandler.getTagValue call throws (invalid XML structure, wrong node type).
Common situations: Hand-edited or corrupted .ktr files, transformations produced by older/newer Pentaho versions with different step XML layout, copy-paste corruption of XML.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- CubeOutputMeta.Exception.UnableToLoadStepInfo
- DelayMeta.Exception.UnableToReadStepInfo
- RulesMeta.Error.LoadFromXML
- RulesMeta.Error.LoadFromXML
- Unable to read step information from XML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/3d0c5ee526a7ed69.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/pgpdecryptstream/PGPDecryptStreamMeta.java:233
retval.append( " " ).append(
XMLHandler.addTagValue( "passhrase", Encr.encryptPasswordIfNotUsingVariables( passhrase ) ) );
retval.append( " " + XMLHandler.addTagValue( "streamfield", streamfield ) );
retval.append( " " + XMLHandler.addTagValue( "resultfieldname", resultfieldname ) );
retval.append( " " + XMLHandler.addTagValue( "passphraseFromField", passphraseFromField ) );
retval.append( " " + XMLHandler.addTagValue( "passphraseFieldName", passphraseFieldName ) );
return retval.toString();
}
private void readData( Node stepnode, List<DatabaseMeta> databases ) throws KettleXMLException {
try {
gpglocation = XMLHandler.getTagValue( stepnode, "gpglocation" );
passhrase = Encr.decryptPasswordOptionallyEncrypted( XMLHandler.getTagValue( stepnode, "passhrase" ) );
streamfield = XMLHandler.getTagValue( stepnode, "streamfield" );
resultfieldname = XMLHandler.getTagValue( stepnode, "resultfieldname" );
passphraseFromField = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "passphraseFromField" ) );
passphraseFieldName = XMLHandler.getTagValue( stepnode, "passphraseFieldName" );
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString(
PKG, "PGPDecryptStreamMeta.Exception.UnableToReadStepInfo" ), e );
}
}
@Override
public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases ) throws KettleException {
try {
gpglocation = rep.getStepAttributeString( id_step, "gpglocation" );
passhrase = Encr.decryptPasswordOptionallyEncrypted( rep.getStepAttributeString( id_step, "passhrase" ) );
streamfield = rep.getStepAttributeString( id_step, "streamfield" );
resultfieldname = rep.getStepAttributeString( id_step, "resultfieldname" );
passphraseFromField = rep.getStepAttributeBoolean( id_step, "passphraseFromField" );
passphraseFieldName = rep.getStepAttributeString( id_step, "passphraseFieldName" );
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString(
PKG, "PGPDecryptStreamMeta.Exception.UnexpectedErrorReadingStepInfo" ), e );
}View on GitHub (pinned to f3058517a1)