pentaho/pentaho-kettle · error · KettleXMLException
Unable to load step info from XML
Error message
Unable to load step info from XML
What it means
JsonOutputMeta.readData parses the step's XML definition (<fields> nodes, encoding, output value, etc.) with XMLHandler; any exception during parsing is rethrown as a KettleXMLException 'Unable to load step info from XML'. This happens when a transformation (.ktr) file's JSON Output step XML is malformed or incompatible.
Solutions
- Open the .ktr in a text editor and inspect the <step type="JsonOutput"> block for malformed or missing XML tags.
- Restore the transformation from version control or repository history.
- Recreate the JSON Output step in Spoon and re-configure its fields.
- Upgrade/align the PDI and JSON plugin versions so the XML schema matches.
Example fix
// before (corrupt ktr XML) <field><name>foo<element>foo</field> // after <field><name>foo</name><element>foo</element></field>
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the ktr XML before loading
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
Document doc = f.newDocumentBuilder().parse(new File("trans.ktr"));
NodeList steps = doc.getElementsByTagName("step");
for (int i = 0; i < steps.getLength(); i++) {
if ("JsonOutput".equals(steps.item(i).getAttributes().getNamedItem("type").getNodeValue())) {
if (((Element) steps.item(i)).getElementsByTagName("fields").getLength() == 0)
throw new IllegalStateException("JsonOutput step missing <fields> block");
}
} Try / catch
try { transMeta = new TransMeta("trans.ktr"); } catch (KettleXMLException e) {
if (e.getMessage().contains("Unable to load step info from XML")) {
log.error("Corrupt/incompatible .ktr; restore from VCS or recreate the step", e);
}
throw e;
} Prevention
- Never hand-edit .ktr files; use Spoon.
- Keep .ktr files in version control so corruption is recoverable.
- Align PDI/plugin versions across environments before moving transformations.
When it happens
Trigger: loadXML calls readData on a Node whose expected tags are missing/corrupt, or XMLHandler throws while reading them (bad XML structure, incompatible plugin version producing unexpected layout).
Common situations: Hand-edited or corrupted .ktr file; opening a transformation created by a newer/older PDI version; partial file from a failed save or bad merge; repository object XML truncated.
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
- Error loading transformation step from XML
- Error loading transformation step from XML
- GetSequenceMeta.Exception.ErrorLoadingStepInfo
- MappingInputMeta.Exception.UnableToLoadStepInfoFromXML
- Unable to find element in the step XML
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/c481f74e0bf13725.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/json/core/src/main/java/org/pentaho/di/trans/steps/jsonoutput/JsonOutputMeta.java:298
dateInFilename = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "file", "add_date" ) );
timeInFilename = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "file", "add_time" ) );
DoNotOpenNewFileInit = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "file", "DoNotOpenNewFileInit" ) );
servletOutput = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "file", "servlet_output" ) );
Node fields = XMLHandler.getSubNode( stepnode, "fields" );
int nrfields = XMLHandler.countNodes( fields, "field" );
allocate( nrfields );
for ( int i = 0; i < nrfields; i++ ) {
Node fnode = XMLHandler.getSubNodeByNr( fields, "field", i );
outputFields[i] = new JsonOutputField();
outputFields[i].setFieldName( XMLHandler.getTagValue( fnode, "name" ) );
outputFields[i].setElementName( XMLHandler.getTagValue( fnode, "element" ) );
}
} catch ( Exception e ) {
throw new KettleXMLException( "Unable to load step info from XML", e );
}
}
public void setDefault() {
encoding = Const.XML_ENCODING;
outputValue = "outputValue";
jsonBloc = "data";
nrRowsInBloc = "1";
operationType = OPERATION_TYPE_WRITE_TO_FILE;
extension = "js";
int nrfields = 0;
allocate( nrfields );
for ( int i = 0; i < nrfields; i++ ) {
outputFields[i] = new JsonOutputField();
outputFields[i].setFieldName( "field" + i );
outputFields[i].setElementName( "field" + i );View on GitHub (pinned to f3058517a1)