pentaho/pentaho-kettle · error · KettleStepException
Xslt.Exception.ErrorXSLFileNotExists
Error message
Xslt.Exception.ErrorXSLFileNotExists
What it means
The configured XSL stylesheet file does not exist on the filesystem. processRow resolves the filename with environment substitution, obtains a VFS FileObject via KettleVFS, and if !file.exists() logs 'ErrorXSLFileNotExists' and throws this KettleStepException containing the resolved path.
Solutions
- Verify the resolved path exists on the machine executing the transformation (note environment substitution of variables).
- Use an absolute path or ${Internal.Transformation.Filename.Directory} to anchor the stylesheet relative to the .ktr.
- Copy the XSL file to the execution server if running on a cluster/remote agent.
- Check the variable value with a 'Get variables' step or Spoon's variable viewer.
Example fix
// before
XSL filename: transform.xsl // relative, missing on server
// after
XSL filename: ${Internal.Transformation.Filename.Directory}/transform.xsl Defensive patterns
Strategy: validation
Validate before calling
String path = transMeta.environmentSubstitute(meta.getXslFilename()); java.io.File f = new java.io.File(path); if (!f.exists() || !f.isFile()) { throw new IllegalStateException("XSL file does not exist: " + path); } // before execution Try / catch
try { step.startThreads(); } catch (KettleStepException e) { if (e.getMessage().contains("ErrorXSLFileNotExists")) { /* check resolved path on the executing host */ } } Prevention
- Deploy XSL files alongside the .ktr to all execution nodes
- Use absolute paths or ${Internal.Transformation.Filename.Directory}
- Log the environment-substituted path during setup to debug variable issues
- Check file existence in a pre-run job step (Check if file exists)
When it happens
Trigger: processRow's one-time setup: KettleVFS.getFileObject(data.xslfilename).exists() returns false for the environment-substituted XSL filename.
Common situations: Typo in the path; file deployed only on the designer machine but not the execution server/agent; relative path resolved against a different working directory; variable like ${XSL_FILE} unset so path becomes literal or empty; file deleted or renamed after configuration.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ChangeFileEncoding.Error.SourceFileNotExists
- Error retrieving command string
- file [ + ArgList[0] + ] can not be found!
- GetXMLDataDialog.Exception.FileDoesNotExist
- SFTPPut.Error.CanNotFindField
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/4fa13cd16ac27bc4.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/xml/core/src/main/java/org/pentaho/di/trans/steps/xslt/Xslt.java:137
+ "]" );
throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLFileFieldFinding", meta
.getXSLFileField() ) );
}
} else {
if ( Utils.isEmpty( meta.getXslFilename() ) ) {
logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLFile" ) );
throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLFile" ) );
}
// Check if XSL File exists!
data.xslfilename = environmentSubstitute( meta.getXslFilename() );
FileObject file = null;
try {
file = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( data.xslfilename );
if ( !file.exists() ) {
logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLFileNotExists", data.xslfilename ) );
throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLFileNotExists",
data.xslfilename ) );
}
if ( file.getType() != FileType.FILE ) {
logError( BaseMessages.getString( PKG, "Xslt.Log.ErrorXSLNotAFile", data.xslfilename ) );
throw new KettleStepException( BaseMessages.getString( PKG, "Xslt.Exception.ErrorXSLNotAFile",
data.xslfilename ) );
}
} catch ( Exception e ) {
throw new KettleStepException( e );
} finally {
try {
if ( file != null ) {
file.close();
}
} catch ( Exception e ) { /* Ignore */
}
}
}View on GitHub (pinned to f3058517a1)