pentaho/pentaho-kettle · error · KettleException
ExcelInput.Log.UnsafeFileException
ExcelInput.Log.UnsafeFileException
Error message
ExcelInput.Log.UnsafeFileException (localized message) + e
What it means
prepareNextOutputFile() specifically catches IOException and POIXMLException when opening the new Excel output file and throws a KettleException containing the localized 'ExcelInput.Log.UnsafeFileException' message concatenated with the exception. This signals the output file could not be safely opened/written by POI.
Solutions
- Ensure the target file is not open/locked in Excel or another process
- If appending, confirm the existing file is a genuine workbook matching its extension
- Delete/replace a corrupt output file and rerun
- Check disk space and write permission on the output directory
- Read the appended exception text in the message for the exact POI/IO cause
Example fix
// before: file renamed to .xlsx but actually old .xls content // after: re-save the file in the correct format (xlsx) or change the step's Extension setting to xls
Defensive patterns
Strategy: try-catch
Validate before calling
File f = new File(filename);
if (f.exists() && f.length() == 0) { /* safe to overwrite */ }
else if (f.exists()) {
try (InputStream in = new FileInputStream(f)) {
byte[] magic = new byte[4]; in.read(magic);
boolean isZip = (magic[0] == 'P' && magic[1] == 'K'); // xlsx
boolean isOle2 = (magic[0] == (byte)0xD0 && magic[1] == (byte)0xCF); // xls
// ensure magic matches the configured extension
}
} Try / catch
try { writer.prepareNextOutputFile(); }
catch (KettleException e) {
if (e.getCause() instanceof IOException || e.getCause() instanceof POIXMLException) {
logError("Unsafe/locked/corrupt output file: " + filename, e);
}
setErrors(1);
throw e;
} Prevention
- Never append to files not created by this step
- Keep extension and actual file format consistent
- Ensure the file is not open in Excel during execution
- Close stale handles (antivirus, prior runs) before rerunning
When it happens
Trigger: IOException creating the output stream or file; POIXMLException from POI when constructing the workbook (corrupt template, mismatched OLE2/OOXML content, zip errors in an xlsx).
Common situations: Appending to a file whose content is not a valid workbook (e.g. it is actually HTML or a renamed file); template copied in place is corrupt; output path is a directory or locked by Excel having the file open; extension says xlsx but content is xls.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- Error opening new file (logged), KettleException( e )
- Error writing field (posX,posY) (logged), KettleException(…
- Could not delete stale file " + buildFilename
- e (no own message; error opening CSV file)
- ExcelInput.Exception.MissingRequiredFiles
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/050ccddc712a2419.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/excel/core/src/main/java/org/pentaho/di/trans/steps/excelwriter/ExcelWriterStep.java:778
// may have to write a header here
if ( meta.isHeaderEnabled() && !( !data.createNewSheet && meta.isAppendOmitHeader() && appendingToSheet ) ) {
writeHeader();
}
// If it's to use streaming, initialize it now as we already made all necessary initial calculations.
if ( data.wb instanceof XSSFWorkbook && meta.isStreamingData() ) {
data.innerSheet = Optional.of( data.sheet );
data.wb = new SXSSFWorkbook( (XSSFWorkbook) data.wb, STREAMING_WINDOW_SIZE );
data.sheet = data.wb.getSheet( data.realSheetname );
}
if ( log.isDebug() ) {
logDebug( BaseMessages.getString( PKG, "ExcelWriterStep.Log.FileOpened", buildFilename ) );
}
// this is the number of the new output file
data.splitnr++;
} catch ( IOException | POIXMLException e ) {
throw new KettleException( BaseMessages.getString( PKG, "ExcelInput.Log.UnsafeFileException" ) +
e
);
}
catch ( Exception e ) {
logError( "Error opening new file", e );
setErrors( 1 );
throw new KettleException( e );
}
}
/** Sets data.startingRow, data.startingCol, data.posX, data.posY */
private void setSheetPosition( boolean appendingToSheet ) {
// starting cell support
if ( !Utils.isEmpty( data.realStartingCell ) ) {
CellReference cellRef = new CellReference( data.realStartingCell );
data.startingRow = cellRef.getRow();
data.startingCol = cellRef.getCol();
} else {View on GitHub (pinned to f3058517a1)