pentaho/pentaho-kettle · error · KettleException
KettleException( e )
Error message
KettleException( e )
What it means
ExcelWriterStep.closeOutputFile closes the underlying workbook (data.wb) and wraps any IOException in a bare KettleException. It means the generated Excel workbook could not be flushed/closed, so the output file may be incomplete or corrupt.
Solutions
- Check the wrapped IOException cause for disk/permission/lock details.
- Ensure the output file is not open in Excel or held by another process during the run.
- Verify free disk space and write permissions in the output directory.
- Write to a local temp file and move it to the final location after success.
- If writing to a network share, confirm the share is stable or write locally first.
Example fix
// before: closing workbook while file is locked FileOutputStream fos = new FileOutputStream( lockedFile ); // Excel has it open // after: verify writability and write atomically File tmp = File.createTempFile( "out", ".xlsx", outputDir ); // write workbook to tmp, then: Files.move( tmp.toPath(), target.toPath(), StandardCopyOption.REPLACE_EXISTING );
Defensive patterns
Strategy: try-catch
Validate before calling
File target = new File( outputPath ); if ( target.exists() && !target.canWrite() ) throw new IllegalStateException( "Output file locked: " + target ); if ( target.getFreeSpace() < minRequiredBytes ) throw new IllegalStateException( "Low disk space" );
Try / catch
try { workbook.close(); } catch ( IOException | KettleException e ) { logError( "Workbook close failed, output may be corrupt: " + e.getMessage(), e ); } Prevention
- Never open the output file in Excel while the transformation runs.
- Monitor free disk space on the output volume.
- Write to a temp file and atomically move to the final name.
When it happens
Trigger: closeOutputFile() calls data.wb.close() (or write()) and an IOException occurs — disk full, stream already closed, file locked by another process, or the underlying output stream failed.
Common situations: Target disk quota/full filesystem; the output file is open in Excel or another reader while the transformation writes; permission changes on the output directory; network drive disconnect during write of a large sheet.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Couldn't write to the database cache
- Error writing line :" + e.toString() (logged)…
- KettleException( e )
- Already closed
- Already closed
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/cac58cc4c6e53437.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/excel/core/src/main/java/org/pentaho/di/trans/steps/excelwriter/ExcelWriterStep.java:299
extendDataValidationRanges();
}
// force recalculation of formulas if requested
if ( meta.isForceFormulaRecalculation() ) {
recalculateAllWorkbookFormulas();
}
data.wb.write( out );
if( data.wb instanceof SXSSFWorkbook ) {
SXSSFWorkbook sxssfWorkbook = (SXSSFWorkbook) data.wb;
sxssfWorkbook.dispose();
sxssfWorkbook.close();
}
else {
data.wb.close();
}
} catch ( IOException e ) {
throw new KettleException( e );
} finally {
IOUtils.closeQuietly( data.wb );
data.wb = null;
}
}
private void extendDataValidationRanges() {
DataValidationHelper helper = data.sheet.getDataValidationHelper();
for ( DataValidation validation : data.sheet.getDataValidations() ) {
CellRangeAddressList rangeList = validation.getRegions();
// extend ranges that include data rows
boolean updated = false;
for ( CellRangeAddress range : rangeList.getCellRangeAddresses() ) {
// extend any ranges that apply to the first data row but not the last
if ( range.containsRow( data.startingRow ) && !range.containsRow( data.posY ) ) {
range.setLastRow( data.posY );
updated = true;
}View on GitHub (pinned to f3058517a1)