pentaho/pentaho-kettle · error · KettleXMLException
GPBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
Error message
GPBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
What it means
GPBulkLoaderMeta.readData() parses the step's XML node to restore saved settings. Any unexpected exception during parsing (missing element dereferenced, wrong data type, malformed XML structure) is wrapped in a KettleXMLException whose message is the localized 'UnableToReadStepInfoFromXML' string. It is a generic deserialization-failure wrapper for this step's metadata.
Solutions
- Look at e.getCause() (and its stack trace line in readData) to find which attribute failed to parse.
- Open the transformation in Spoon and re-save the GP Bulk Loader step so it regenerates valid XML.
- Compare the step's <fields> XML block against a freshly created step and fix/remove the malformed element.
- Upgrade or align the gp-bulk-loader plugin version with the one that wrote the transformation file.
Example fix
// before: hand-edited step XML missing <field> sub-elements <field><name>id</name></field> // after: complete schema as written by Spoon <field> <column_name>id</column_name> <stream_name>id</stream_name> <date_mask></date_mask> </field>
Defensive patterns
Strategy: try-catch
Validate before calling
// validate the step XML before loading it
org.w3c.dom.Node stepNode = /* the <step> node */;
if (!"GPBulkLoader".equals(
org.pentaho.di.core.xml.XMLHandler.getTagValue(stepNode, "type")))
throw new IllegalArgumentException("Node is not a GPBulkLoader step");
if (org.pentaho.di.core.xml.XMLHandler.getNodes(stepNode, "fields").isEmpty())
throw new IllegalArgumentException("GPBulkLoader step XML missing <fields> block"); Try / catch
try {
transMeta.loadXML(file, null, null, null, null, true, listener);
} catch (KettleXMLException e) {
if (e.getMessage().contains("UnableToReadStepInfoFromXML")) {
logError("GPBulkLoader step XML unreadable", e.getCause());
// re-create the step in Spoon or repair the XML element identified by the cause
} else throw e;
} Prevention
- Never hand-edit transformation XML; configure steps through Spoon
- Keep the gp-bulk-loader plugin version consistent across environments
- When importing transformations, re-save suspicious steps to regenerate valid XML
When it happens
Trigger: loadXML(node, ...) -> readData(node) encounters malformed or unexpected XML: an expected child element is absent so a lookup returns null and later code dereferences it; attribute values cannot be parsed (e.g. non-numeric where a number is expected); the XML node passed belongs to a different step or an incompatible plugin version.
Common situations: Transformation XML hand-edited and an element removed/renamed; transformation produced by a much older or newer plugin version with a schema change; corrupted repository export; copy-paste of step XML between transformations with incompatible metadata.
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
- GPLoadMeta.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/961f00b67d87199b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/gp-bulk-loader/core/src/main/java/org/pentaho/di/trans/steps/gpbulkloader/GPBulkLoaderMeta.java:291
fieldTable[i] = XMLHandler.getTagValue( vnode, "stream_name" );
fieldStream[i] = XMLHandler.getTagValue( vnode, "field_name" );
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 ( GPBulkLoaderMeta.DATE_MASK_DATE.equals( locDateMask )
|| GPBulkLoaderMeta.DATE_MASK_DATETIME.equals( locDateMask ) ) {
dateMask[i] = locDateMask;
} else {
dateMask[i] = "";
}
}
}
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString(
PKG, "GPBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML" ), e );
}
}
@Override
public void setDefault() {
fieldTable = null;
databaseMeta = null;
maxErrors = 50;
schemaName = "";
tableName = BaseMessages.getString( PKG, "GPBulkLoaderMeta.DefaultTableName" );
loadMethod = METHOD_AUTO_END;
loadAction = ACTION_APPEND;
PsqlPath = "PsqlPath";
controlFile = "control${Internal.Step.CopyNr}.cfg";
dataFile = "load${Internal.Step.CopyNr}.dat";
logFile = "";
encoding = "";View on GitHub (pinned to f3058517a1)