pentaho/pentaho-kettle · error · KettleXMLException
JobMeta.Exception.ErrorReadingFromXMLFile
Error message
JobMeta.Exception.ErrorReadingFromXMLFile
What it means
JobMeta.loadXML from file: after parsing the document, if the <job> root node (XML_TAG) is absent, doc is non-null but jobnode is effectively null/unusable and this message (plus the file name) is thrown as a KettleXMLException. It means the file exists and parses as XML but is not a Pentaho job document.
Solutions
- Verify the file's root element is <job>; if it is <transformation> you are loading a .ktr with the wrong loader.
- Re-export or restore the .kjb from backup/version control if it is truncated.
- Open the file in a text editor and confirm it starts with <?xml ...?><job> and is complete to </job>.
- Load via Spoon to see a friendlier diagnostic, then re-save.
- Check you are not passing an archive (zip) path instead of the extracted job XML.
Example fix
// before: loading a transformation as a job
JobMeta jobMeta = new JobMeta();
jobMeta.loadXML("etl.ktr", null, repo, metaStore, null); // not a <job> doc
// after
if (isTransformationFile("etl.ktr")) {
TransMeta transMeta = new TransMeta("etl.ktr");
} else {
JobMeta jobMeta = new JobMeta("etl.kjb", repo, metaStore, null);
} Defensive patterns
Strategy: validation
Validate before calling
Document doc = XMLHandler.loadXMLFile(new File(fileName));
if (doc == null || XMLHandler.getSubNode(doc, "job") == null) {
throw new IllegalArgumentException(fileName + " is not a job XML document (missing <job> root)");
} Try / catch
try {
jobMeta.loadXML(fname, rep, metaStore, prompter);
} catch (KettleXMLException e) {
if (e.getMessage().contains("ErrorReadingFromXMLFile") || e.getMessage().contains(fname)) {
throw new IllegalArgumentException("Not a valid .kjb file: " + fname, e);
}
throw e;
} Prevention
- Check the root element (<job> vs <transformation>) before choosing the loader.
- Verify file completeness (ends with </job>) after downloads or syncs.
- Do not rename .ktr to .kjb (or vice versa) expecting the loader to cope.
- Open questionable files in Spoon first to confirm they load.
When it happens
Trigger: Calling JobMeta load-from-file with a file that parses to a DOM whose root is not <job> — e.g. passing a .ktr transformation, an export archive member, a configuration file, or a truncated .kjb missing its root element.
Common situations: Wrong file passed to the loader (transformation vs job); file extension renamed but content changed; partially downloaded/truncated .kjb; XML with wrong namespace or an extra wrapper root added by export tools.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- JobMeta.Exception.UnableToLoadJobFromXMLFile
- JobMeta.Exception.UnableToLoadJobFromXMLNode
- AbortMeta.Exception.UnexpectedErrorInReadingStepInfoFromRepo…
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
- AggregateRowsMeta.Exception.UnableToLoadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/e221dfb0567b74df.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/job/JobMeta.java:885
* @param fname The filename to load as a job
* @param rep The repository to bind againt, null if there is no repository available.
* @throws KettleXMLException
*/
public JobMeta( Bowl bowl, VariableSpace parentSpace, String fname, Repository rep, IMetaStore metaStore,
OverwritePrompter prompter ) throws KettleXMLException {
this.initializeVariablesFrom( parentSpace );
this.metaStore = metaStore;
setBowl( bowl );
try {
// OK, try to load using the VFS stuff...
Document doc = XMLHandler.loadXMLFile( KettleVFS.getInstance( bowl ).getFileObject( fname, this ) );
if ( doc != null ) {
// The jobnode
Node jobnode = XMLHandler.getSubNode( doc, XML_TAG );
loadXML( jobnode, fname, rep, metaStore, false, prompter );
} else {
throw new KettleXMLException(
BaseMessages.getString( PKG, "JobMeta.Exception.ErrorReadingFromXMLFile" ) + fname );
}
} catch ( Exception e ) {
throw new KettleXMLException(
BaseMessages.getString( PKG, "JobMeta.Exception.UnableToLoadJobFromXMLFile" ) + fname + "]", e );
}
}
/**
* Instantiates a new job meta.
*
* @param inputStream the input stream
* @param rep the rep
* @param prompter the prompter
* @throws KettleXMLException the kettle xml exception
*/
public JobMeta( InputStream inputStream, Repository rep, OverwritePrompter prompter ) throws KettleXMLException {
this();View on GitHub (pinned to f3058517a1)