pentaho/pentaho-kettle · error · KettleXMLException

StringOperationsMeta.Exception.UnableToReadStepInfoFromXML

Error message

StringOperationsMeta.Exception.UnableToReadStepInfoFromXML

What it means

StringOperationsMeta throws this KettleXMLException in readData() (called from loadXML) when parsing the step's XML definition fails unexpectedly. The wrapper keeps the original exception as the cause. The step cannot be loaded from the .ktr until the XML structure is corrected.

Solutions

  1. Inspect the wrapped cause to pinpoint the malformed XML element
  2. Repair the <fields><field> section of the step XML so each field node has the expected tags
  3. Regenerate the step XML by re-saving it from Spoon
  4. Restore the .ktr from version control or backup

Example fix

// before
<field><field_in>a</field_in> <!-- missing required child tags -->
// after
<field><field_in>a</field_in><field_out>b</field_out><trim_type>none</trim_type><mask_xml></mask_xml><digits>none</digits><remove_special_characters>none</remove_special_characters></field>
Defensive patterns

Strategy: try-catch

Validate before calling

// check the fields node before loadXML
Node fieldsNode = XMLHandler.getSubNode(stepnode, "fields");
if (fieldsNode == null) {
  logBasic("No fields node; step will use defaults");
}
for (int i = 0; fieldsNode != null && i < XMLHandler.countNodes(fieldsNode, "field"); i++) {
  Node f = XMLHandler.getSubNodeByNr(fieldsNode, "field", i);
  if (XMLHandler.getTagValue(f, "field_in") == null) {
    throw new IllegalArgumentException("Missing field_in at field #" + i);
  }
}

Type guard

boolean isParsableFieldsNode(Node stepnode) {
  Node fields = XMLHandler.getSubNode(stepnode, "fields");
  return fields == null || XMLHandler.countNodes(fields, "field") >= 0;
}

Try / catch

try {
  meta.loadXML(stepnode, databases, context);
} catch (KettleXMLException e) {
  logError("Bad StringOperations XML: " + e.getCause(), e);
  meta.setDefault(); // degrade gracefully
}

Prevention

When it happens

Trigger: Calling loadXML() when XMLHandler.getTagValue(fnode, ...) or the field-array setup throws — malformed <fields>/<field> nodes, unexpected null elements, or DOM errors while reading field_in/mask_xml/digits/remove_special_characters tags.

Common situations: Hand-edited or truncated .ktr XML; XML generated by a different PDI version with a diverged schema; corrupted file after a bad merge or transfer.

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


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/5e5ef734fa19fde9. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/stringoperations/StringOperationsMeta.java:422

      for ( int i = 0; i < nrkeys; i++ ) {
        Node fnode = XMLHandler.getSubNodeByNr( lookup, "field", i );

        fieldInStream[i] = Const.NVL( XMLHandler.getTagValue( fnode, "in_stream_name" ), "" );
        fieldOutStream[i] = Const.NVL( XMLHandler.getTagValue( fnode, "out_stream_name" ), "" );

        trimType[i] = Const.NVL( XMLHandler.getTagValue( fnode, "trim_type" ), "" );
        lowerUpper[i] = Const.NVL( XMLHandler.getTagValue( fnode, "lower_upper" ), "" );
        padding_type[i] = Const.NVL( XMLHandler.getTagValue( fnode, "padding_type" ), "" );
        padChar[i] = Const.NVL( XMLHandler.getTagValue( fnode, "pad_char" ), "" );
        padLen[i] = Const.NVL( XMLHandler.getTagValue( fnode, "pad_len" ), "" );
        initCap[i] = Const.NVL( XMLHandler.getTagValue( fnode, "init_cap" ), "" );
        maskXML[i] = Const.NVL( XMLHandler.getTagValue( fnode, "mask_xml" ), "" );
        digits[i] = Const.NVL( XMLHandler.getTagValue( fnode, "digits" ), "" );
        remove_special_characters[i] = Const.NVL( XMLHandler.getTagValue( fnode, "remove_special_characters" ), "" );

      }
    } catch ( Exception e ) {
      throw new KettleXMLException( BaseMessages.getString(
        PKG, "StringOperationsMeta.Exception.UnableToReadStepInfoFromXML" ), e );
    }
  }

  @Override
  public void setDefault() {
    fieldInStream = null;
    fieldOutStream = null;

    int nrkeys = 0;

    allocate( nrkeys );
  }

  @Override
  public String getXML() {
    StringBuilder retval = new StringBuilder( 500 );

View on GitHub (pinned to f3058517a1)