pentaho/pentaho-kettle · error · KettleXMLException

Unable to load step info from XML

Error message

Unable to load step info from XML

What it means

SalesforceInsertMeta.readData() wraps the whole XML deserialization of the step's configuration in a try/catch and rethrows any exception as a KettleXMLException with the generic message 'Unable to load step info from XML'. It means the <step> XML node for a Salesforce Insert step could not be parsed — typically a malformed tag, missing attribute, or an unexpected value when the transformation .ktr file was read. The original cause is chained as the 'cause' of the KettleXMLException.

Solutions

  1. Read the chained cause (e.getCause()) of the KettleXMLException — it names the exact tag/value that failed to parse.
  2. Open the .ktr in a text editor and locate the Salesforce Insert <step> XML block; fix malformed/missing tags or remove the step and re-add it in Spoon.
  3. Regenerate the transformation in the same PDI version that will run it (avoid round-tripping across major versions).
  4. If version migration is required, export/import via Spoon rather than editing XML directly.

Example fix

// before: hand-edited step XML
<rollbackAllChangesOnError>yes</rollbackAllChangesOnError>
// after: parser expects Y/N comparison via "Y".equalsIgnoreCase(...)
<rollbackAllChangesOnError>Y</rollbackAllChangesOnError>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the step XML block before loading
org.w3c.dom.NodeList steps = doc.getElementsByTagName("step");
for (int i = 0; i < steps.getLength(); i++) {
  Node n = steps.item(i);
  if (XMLHandler.getTagValue(n, "type").equals("SalesforceInsert")
      && XMLHandler.getTagValue(n, "connection") == null) {
    throw new IllegalArgumentException("SalesforceInsert step XML is incomplete");
  }
}

Try / catch

try {
  transMeta = new TransMeta(ktrFile);
} catch (KettleXMLException e) {
  log.error("Step XML load failed: {}", e.getCause() != null ? e.getCause().getMessage() : e.getMessage(), e);
  throw e;
}

Prevention

When it happens

Trigger: Calling loadXML(Node stepnode, ...) on a SalesforceInsertMeta whose XML node is corrupt: XMLHandler.getTagValue() throws or returns data that fails parsing, e.g. during TransMeta.loadXML of a .ktr file containing a salesforce-insert step whose XML block is hand-edited, truncated, or produced by an incompatible PDI version.

Common situations: Opening a transformation edited by hand or by another tool; upgrading PDI and loading a .ktr written by an older/newer plugin version; a copied XML snippet pasted into the .ktr with missing or malformed child tags like rollbackAllChangesOnError.

Related errors


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

Appendix: source

Thrown at plugins/salesforce/core/src/main/java/org/pentaho/di/trans/steps/salesforceinsert/SalesforceInsertMeta.java:240

          updateStream[i] = updateLookup[i]; // default: the same name!
        }
        String updateValue = XMLHandler.getTagValue( fnode, "useExternalId" );
        if ( updateValue == null ) {
          // default FALSE
          useExternalId[i] = Boolean.FALSE;
        } else {
          if ( updateValue.equalsIgnoreCase( "Y" ) ) {
            useExternalId[i] = Boolean.TRUE;
          } else {
            useExternalId[i] = Boolean.FALSE;
          }
        }
      }
      setRollbackAllChangesOnError(
        "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "rollbackAllChangesOnError" ) ) );

    } catch ( Exception e ) {
      throw new KettleXMLException( "Unable to load step info from XML", e );
    }
  }

  public void allocate( int nrvalues ) {
    setUpdateLookup( new String[nrvalues] );
    setUpdateStream( new String[nrvalues] );
    setUseExternalId( new Boolean[nrvalues] );
  }

  public void setDefault() {
    super.setDefault();
    setBatchSize( "10" );
    setSalesforceIDFieldName( "Id" );

    allocate( 0 );

    setRollbackAllChangesOnError( false );
  }

View on GitHub (pinned to f3058517a1)