pentaho/pentaho-kettle · error · KettleXMLException
MySQLBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
MySQLBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
Error message
MySQLBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML
What it means
readData parses the step's XML representation (via loadXML) and wraps any exception during tag parsing in a KettleXMLException with the UnableToReadStepInfoFromXML message. It means the <step> XML for the MySQL Bulk Loader could not be read: a required tag was missing, malformed, or had an unexpected value. The original exception is attached as the cause.
Solutions
- Open the .ktr file in a text editor and inspect the MySQL Bulk Loader step's <fields> section for missing or malformed tags (field_table, field_stream, field_format_ok).
- Recreate the step in Spoon and save a fresh .ktr to regenerate valid XML.
- Check Kettle version compatibility — if the file came from a newer PDI version, upgrade the runtime or re-save in your version.
- Look at the KettleXMLException's cause (getCause()) to pinpoint the exact parse failure.
Example fix
// before: hand-edited XML with an unrecognized format value <field_format_ok>BigDecimal</field_format_ok> // after: use one of the supported format identifiers <field_format_ok>none</field_format_ok>
Defensive patterns
Strategy: try-catch
Validate before calling
// Before loading, check the .ktr contains well-formed step XML
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( new File( ktrPath ) );
NodeList steps = doc.getElementsByTagName( "step" );
for ( int i = 0; i < steps.getLength(); i++ ) {
Element step = (Element) steps.item( i );
if ( "MySQLBulkLoader".equals( step.getAttribute( "type" ) ) ) {
NodeList fields = step.getElementsByTagName( "fields" );
if ( fields.getLength() == 0 ) {
throw new IllegalStateException( "MySQLBulkLoader step XML missing <fields> element" );
}
}
} Try / catch
try {
transMeta = new TransMeta( ktrPath );
} catch ( KettleXMLException e ) {
if ( String.valueOf( e.getMessage() ).contains( "UnableToReadStepInfoFromXML" ) ) {
log.error( "Corrupt MySQL Bulk Loader step XML; inspect the <fields> block, cause:", e.getCause() );
} else {
throw e;
}
} Prevention
- Never hand-edit .ktr files; edit through Spoon.
- Validate XML before loading programmatically-generated transformations.
- Keep the Kettle runtime version in sync with the tooling that produced the .ktr.
- Verify file integrity (no truncation) after transferring transformations between machines.
When it happens
Trigger: loadXML -> readData throws when XMLHandler.getTagValue returns unexpected content, getFieldFormatType fails on an unknown format string, or any exception occurs while reading field_table/field_stream/field_format_ok tags inside the <fields> element.
Common situations: Manually edited .ktr files with corrupted or missing tags; transformations from a different Pentaho/Kettle version using a different XML schema; truncated file transfer; copy-pasted step XML between transformations with mismatched content.
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
- AnalyticQueryMeta.Exception.UnableToLoadStepInfoFromXML
- FuzzyMatchMeta.Exception.UnableToLoadStepInfoFromXML
- GetPreviousRowFieldMeta.Exception.UnableToReadStepInfoFromXM…
- GetXMLDataMeta.Exception.ErrorLoadingXML (localized message…
- InsertUpdateMeta.Exception.UnableToReadStepInfoFromXML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/0e935b61518975b9.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/mysql-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/mysqlbulkloader/MySQLBulkLoaderMeta.java:275
replacingData = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "replace" ) );
ignoringErrors = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "ignore" ) );
localFile = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "local" ) );
int nrvalues = XMLHandler.countNodes( stepnode, "mapping" );
allocate( nrvalues );
for ( int i = 0; i < nrvalues; i++ ) {
Node vnode = XMLHandler.getSubNodeByNr( stepnode, "mapping", i );
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!
}
fieldFormatType[i] = getFieldFormatType( XMLHandler.getTagValue( vnode, "field_format_ok" ) );
}
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString( PKG,
"MySQLBulkLoaderMeta.Exception.UnableToReadStepInfoFromXML" ), e );
}
}
public void setDefault() {
fieldTable = null;
databaseMeta = null;
schemaName = "";
tableName = BaseMessages.getString( PKG, "MySQLBulkLoaderMeta.DefaultTableName" );
encoding = "";
fifoFileName = "/tmp/fifo";
delimiter = "\t";
enclosure = "\"";
escapeChar = "\\";
replacingData = false;
ignoringErrors = false;
localFile = true;
bulkSize = null;View on GitHub (pinned to f3058517a1)