pentaho/pentaho-kettle · error · KettleException
Template file missing: " + data.realTemplateFileName
Error message
Template file missing: " + data.realTemplateFileName
What it means
With 'Use template' enabled, createFile() checks whether the template file exists via VFS. If it does not, it logs 'TemplateMissing' at basic level, sets the step error count, and throws KettleException("Template file missing: <path>").
Solutions
- Verify the template file exists at the exact path shown in the message
- Use an absolute path for the template filename
- Check drive mounts/permissions if the template is on a network share
- Ensure the step that generates the template ran before this step (ordering in the transformation)
- Check filename casing on Linux filesystems
Example fix
// before String template = "templates/report_template.xlsx"; // relative, breaks in kitchen // after String template = "/opt/pdi/templates/report_template.xlsx"; // absolute path
Defensive patterns
Strategy: validation
Validate before calling
String resolved = environmentSubstitute(templatePath);
File t = new File(resolved);
if (!t.isFile()) throw new IllegalStateException("Template file missing: " + t.getAbsolutePath());
if (!t.canRead()) throw new IllegalStateException("Template not readable: " + t.getAbsolutePath()); Prevention
- Use absolute template paths
- On Linux, verify filename casing
- Ensure upstream template-generation steps run first
- Check network drive availability before scheduled runs
When it happens
Trigger: Template file path (static or resolved from a field) points to a nonexistent file at createFile time: wrong path, file deleted, relative path resolving differently at runtime, or template not yet generated by an earlier step.
Common situations: Template stored on a network drive that is not mounted; relative paths broken when running in a different working directory; template generation step failed silently upstream; case-sensitive Linux filesystem vs Windows-style path casing.
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
- ExcelWriterStep.Exception.TemplateNotFound
- Template Format Mismatch: Template has extension: " +…
- AccessInput.Log.RequiredFilesMissing
- ChangeFileEncoding.Error.SourceFileNotExists
- Could not delete stale file " + buildFilename
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/1d68c90161913506.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/excel/core/src/main/java/org/pentaho/di/trans/steps/excelwriter/ExcelWriterStep.java:882
String templateExt = KettleVFS.getInstance( getTransMeta().getBowl() )
.getFileObject( data.realTemplateFileName ).getName().getExtension();
if ( !meta.getExtension().equalsIgnoreCase( templateExt ) ) {
throw new KettleException(
"Template Format Mismatch: Template has extension: " + templateExt + ", but output file has extension: "
+ meta.getExtension() + ". Template and output file must share the same format!" );
}
if ( KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( data.realTemplateFileName ).exists() ) {
// if the template exists just copy the template in place
copyFile( getTransMeta().getBowl(), KettleVFS.getInstance( getTransMeta().getBowl() )
.getFileObject( data.realTemplateFileName, getTransMeta() ), data.file );
} else {
// template is missing, log it and get out
if ( log.isBasic() ) {
logBasic( BaseMessages.getString( PKG, "ExcelWriterStep.Log.TemplateMissing", data.realTemplateFileName ) );
}
setErrors( 1 );
throw new KettleException( "Template file missing: " + data.realTemplateFileName );
}
} else {
// handle fresh file case, just create a fresh workbook
try ( Workbook wb = XLSX.equalsIgnoreCase( meta.getExtension() ) ? new XSSFWorkbook() : new HSSFWorkbook();
BufferedOutputStreamWithCloseDetection out =
new BufferedOutputStreamWithCloseDetection( KettleVFS.getInstance( getTransMeta().getBowl() )
.getOutputStream( data.file, false ) ) ) {
wb.createSheet( data.realSheetname );
wb.write( out );
}
}
}
private void openLine() {
if ( data.shiftExistingCells ) {
data.sheet.shiftRows( data.posY, Math.max( data.posY, data.sheet.getLastRowNum() ), 1 );
}
}View on GitHub (pinned to f3058517a1)