pentaho/pentaho-kettle · error · KettleXMLException
Unable to load step info from XML
Error message
Unable to load step info from XML
What it means
TableInputMeta.readData(), invoked from loadXML(), parses the step's XML node (connection, SQL, 'execute each input row', lazy conversion, cached row meta tags) via XMLHandler. Any exception during parsing is rethrown as a KettleXMLException with the message 'Unable to load step info from XML'.
Solutions
- Open the .ktr file in an XML editor and validate it; fix or remove the malformed TableInput step node.
- Check the cause chain (KettleXMLException wraps the original exception) to find which tag failed.
- Remove or repair the cached row meta node (xml_meta tag) — it is recomputed at runtime.
- Recreate the TableInput step in Spoon and re-enter its settings, then re-save the transformation.
- Ensure the transformation file was fully written/exported (not truncated) and matches your Pentaho version.
Example fix
// before: missing <row-meta> element breaks new RowMeta(XMLHandler.getSubNode(...)) if code expects it <step name="Table input" type="TableInput"> <sql>SELECT ...</sql> </step> // after: re-save the step via Spoon so all tags are serialized <step name="Table input" type="TableInput"> <sql>SELECT ...</sql> <variables_active>Y</variables_active> <lazy_conversion_active>N</lazy_conversion_active> <cached_row_meta_active>N</cached_row_meta_active> </step>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the .ktr XML parses and contains the TableInput node before loading
Document doc = XMLHandler.loadXMLFile(new File("trans.ktr"));
if (doc == null || XMLHandler.getSubNode(doc.getDocumentElement(), "step") == null) {
throw new IllegalStateException("Transformation XML is malformed");
} Try / catch
try {
meta.loadXML(stepnode, databases, metaStore);
} catch (KettleXMLException e) {
log.error("Step XML invalid: " + KettleUtil.getMessage(e));
throw e; // or recreate the step from defaults: meta.setDefault();
} Prevention
- Never hand-edit .ktr files; edit via Spoon and let it serialize the step.
- Validate XML after copying steps between transformations.
- Check for full/clean file writes when exporting transformations.
- When upgrading Pentaho versions, re-save transformations so tag schemas match.
When it happens
Trigger: loadXML() is called with a stepnode whose expected tags are malformed or whose cached row-meta subnode (RowMeta.XML_META_TAG) is missing/corrupt, causing XMLHandler.getSubNode/new RowMeta to throw; also a null or non-element stepnode.
Common situations: Hand-edited or truncated .ktr files; transformations exported by other tools or older/newer Pentaho versions missing tags like <row-meta>; copy-pasting step XML fragments between transformations; corrupted repository/export files.
Related errors
- MappingInputMeta.Exception.UnableToLoadStepInfoFromXML
- Unable to load step info from XML
- Unable to load step info from XML
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
- AggregateRowsMeta.Exception.UnableToLoadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/d76ee16578878a4a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/tableinput/TableInputMeta.java:188
private void readData( Node stepnode, List<DatabaseMeta> databases ) throws KettleXMLException {
this.databases = databases;
try {
databaseMeta = DatabaseMeta.findDatabase( databases, XMLHandler.getTagValue( stepnode, "connection" ) );
sql = XMLHandler.getTagValue( stepnode, "sql" );
rowLimit = XMLHandler.getTagValue( stepnode, "limit" );
String lookupFromStepname = XMLHandler.getTagValue( stepnode, "lookup" );
StreamInterface infoStream = getStepIOMeta().getInfoStreams().get( 0 );
infoStream.setSubject( lookupFromStepname );
executeEachInputRow = "Y".equals( XMLHandler.getTagValue( stepnode, "execute_each_row" ) );
variableReplacementActive = "Y".equals( XMLHandler.getTagValue( stepnode, "variables_active" ) );
lazyConversionActive = "Y".equals( XMLHandler.getTagValue( stepnode, "lazy_conversion_active" ) );
cachedRowMetaActive = "Y".equals( XMLHandler.getTagValue( stepnode, "cached_row_meta_active" ) );
cachedRowMeta = new RowMeta( XMLHandler.getSubNode( stepnode, RowMeta.XML_META_TAG ) );
} catch ( Exception e ) {
throw new KettleXMLException( "Unable to load step info from XML", e );
}
}
public void setDefault() {
databaseMeta = null;
sql = "SELECT <values> FROM <table name> WHERE <conditions>";
rowLimit = "0";
}
protected Database getDatabase() {
// Added for test purposes
return new Database( loggingObject, databaseMeta );
}
@Override
public void getFields( Bowl bowl, RowMetaInterface row, String origin, RowMetaInterface[] info, StepMeta nextStep,
VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {
if ( databaseMeta == null ) {View on GitHub (pinned to f3058517a1)