pentaho/pentaho-kettle · error · KettleXMLException
GPLoadMeta.Exception.UnableToReadStepInfoFromXML
Error message
GPLoadMeta.Exception.UnableToReadStepInfoFromXML
What it means
GPLoadMeta.readData() parses the step's XML definition with XMLHandler; any exception during tag reads is wrapped in a KettleXMLException with this message. It indicates the GPload step's XML serialization is malformed or missing expected elements.
Solutions
- Open the .ktr in Spoon and reconfigure/save the GPload step to regenerate valid XML
- Compare the step's XML block against a freshly created GPload step's XML and repair missing/renamed tags
- Align the PDI and GPload plugin versions (the XML schema must match the plugin's readData expectations)
- Restore the .ktr from backup if the file was truncated/corrupted
Example fix
// before (missing tag) <fields><field><name>a</name></field></fields> // after <fields><field><name>a</name><field_name>a</field_name><date_mask/><match_column>N</match_column><update_column>N</update_column></field></fields>
Defensive patterns
Strategy: try-catch
Validate before calling
org.w3c.dom.Node stepNode = ...; // verify required tags exist before loadXML
for (String tag : new String[]{"connection","table","data_file","delimiter","fields"}) {
if (XMLHandler.getTagValue(stepNode, tag) == null && XMLHandler.getSubNode(stepNode, tag) == null) {
throw new IllegalArgumentException("GPload step XML missing tag: " + tag);
}
} Try / catch
try { stepMeta.loadXML(...) } catch (KettleXMLException e) {
if (e.getMessage().contains("UnableToReadStepInfoFromXML")) { /* fall back to re-creating the step from defaults */ }
else throw e;
} Prevention
- Never hand-edit .ktr XML; use Spoon to modify steps
- Keep PDI and plugin versions consistent across environments that share .ktr files
- Validate .ktr files (open in Spoon) after any scripted generation
- Keep backups of transformations before scripted edits
When it happens
Trigger: loadXML() calls readData on a <step> node whose children (connection, table, field_name/match_column/update_column entries, etc.) are missing, of wrong shape, or whose structure differs from what this plugin version expects.
Common situations: Hand-edited or truncated .ktr files; .ktr created in a different PDI/plugin version with changed XML schema; XML attribute names changed between plugin versions; copy-pasting a GPload step snippet that omits required tags.
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
- GetTableNamesMeta.Exception.UnableToReadStepInfo
- GPBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
- MappingMeta.Exception.ErrorLoadingTransformationStepFromXML
- MultiMergeJoinMeta.Exception.UnableToLoadStepInfo
- NormaliserMeta.Exception.UnableToLoadStepInfoFromXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/db9977fb5273a4b7.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoadMeta.java:378
if ( fieldStream[i] == null ) {
fieldStream[i] = fieldTable[i]; // default: the same name!
}
String locDateMask = XMLHandler.getTagValue( vnode, "date_mask" );
if ( locDateMask == null ) {
dateMask[i] = "";
} else {
if ( GPLoadMeta.DATE_MASK_DATE.equals( locDateMask ) || GPLoadMeta.DATE_MASK_DATETIME.equals( locDateMask ) ) {
dateMask[i] = locDateMask;
} else {
dateMask[i] = "";
}
}
matchColumn[i] = ( "Y".equalsIgnoreCase( XMLHandler.getTagValue( vnode, "match_column" ) ) );
updateColumn[i] = ( "Y".equalsIgnoreCase( XMLHandler.getTagValue( vnode, "update_column" ) ) );
}
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "GPLoadMeta.Exception.UnableToReadStepInfoFromXML" ),
e );
}
}
public void setDefault() {
// TODO: Make non empty defaults public static Strings
fieldTable = null;
databaseMeta = null;
maxErrors = GPLoadMeta.MAX_ERRORS_DEFAULT;
schemaName = "";
localhostPort = "";
tableName = BaseMessages.getString( PKG, "GPLoadMeta.DefaultTableName" );
errorTableName = ""; // BaseMessages.getString(PKG, "GPLocal.ErrorTable.Prefix")+tableName;
loadMethod = METHOD_AUTO_END;
loadAction = ACTION_INSERT;
gploadPath = "/usr/local/greenplum-db/bin/gpload";View on GitHub (pinned to f3058517a1)