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

  1. Verify the template file exists at the exact path shown in the message
  2. Use an absolute path for the template filename
  3. Check drive mounts/permissions if the template is on a network share
  4. Ensure the step that generates the template ran before this step (ordering in the transformation)
  5. 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

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


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)