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

  1. Open the .ktr in Spoon and re-save the PGP Decrypt Stream step to regenerate valid XML
  2. Validate the XML file is well-formed (xmllint or an XML editor)
  3. Compare the step's XML block against a working transformation and fix missing/renamed tags
  4. 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

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


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)