pentaho/pentaho-kettle · error · KettleException
Can not append to an existing zip file
Error message
Can not append to an existing zip file : {filename} What it means
initFileStreamWriter refuses to append to a ZIP-compressed target: ZIP archives cannot be reopened for appending, so when 'Append' is enabled on the Text File Output step, the compression provider is the ZIP provider, and the target file already exists, a KettleException 'Can not append to an existing zip file : <filename>' is thrown before any stream is opened.
Solutions
- Disable the 'Append' option in the Text File Output step, or delete/move the existing .zip file before running.
- Switch compression to None or GZip if appending is required (GZip supports append via stream concatenation).
- Add a preceding step/job entry that removes the existing file when present.
- Point the output at a new filename (e.g. include a timestamp) so the target does not already exist.
Example fix
// before compression = "Zip", append = true, filename = "out.zip" // out.zip exists // after compression = "Zip", append = false // or: delete out.zip (or use compression "GZip" with append = true)
Defensive patterns
Strategy: validation
Validate before calling
boolean isZip = "Zip".equalsIgnoreCase( meta.getCompressionType() );
if ( isZip && meta.isFileAppended() && new File( filename ).exists() ) {
// delete, rename, or disable append before running
new File( filename ).delete();
} Try / catch
try {
transformation.startExecution();
} catch ( KettleException e ) {
if ( e.getMessage().startsWith( "Can not append to an existing zip file" ) ) {
// remove the zip or turn off append, then re-run
}
} Prevention
- Never combine Append=true with Zip compression in Text File Output
- Pre-clean stale output files in scheduled jobs before re-running
- Use GZip or no compression when append semantics are required
When it happens
Trigger: meta.isFileAppended() is true AND compression is ZIP (getCompressionProvider() instanceof ZIPCompressionProvider) AND isFileExists(filename) is true — i.e. a rerun of a transformation that already produced the zip file with append enabled.
Common situations: Scheduling a transformation to run repeatedly with 'Append to existing file' checked but compression set to Zip; leftover output from a previous failed run sits in the target directory; migrating a step from uncompressed/GZip append to Zip append without clearing old output.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- ZipFile.Error.EmptyMoveToFolder
- ZipFile.Error.SourceFileEmpty
- ZipFile.Error.SourceFileNotExist
- ZipFile.Error.SourceFileNotFile
- ZipFile.Error.TargetFileEmpty
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/f134126e68b99a4a.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/textfileoutput/TextFileOutput.java:157
boolean writingToFileForFirstTime = fileStreams == null;
if ( writingToFileForFirstTime ) { // Opening file for first time
if ( meta.isAddToResultFiles() ) {
// Add this to the result file names...
ResultFile resultFile =
new ResultFile( ResultFile.FILE_TYPE_GENERAL, getFileObject( filename, getTransMeta() ),
getTransMeta().getName(), getStepname() );
resultFile.setComment( BaseMessages.getString( PKG, "TextFileOutput.AddResultFile" ) );
addResultFile( resultFile );
}
CompressionProvider compressionProvider = getCompressionProvider();
boolean isZipFile = compressionProvider instanceof ZIPCompressionProvider;
boolean appendToExistingFile = meta.isFileAppended();
if ( appendToExistingFile && isZipFile && isFileExists( filename ) ) {
throw new KettleException( "Can not append to an existing zip file : " + filename );
}
int maxOpenFiles = getMaxOpenFiles();
if ( ( maxOpenFiles > 0 ) && ( data.getFileStreamsCollection().getNumOpenFiles() >= maxOpenFiles ) ) {
// If the file we're going to close is a zip file, going to remove it from the collection of files
// that have been opened. We do this because it is not possible to reopen a
// zip file for append. By removing it from the collection, if the same file is referenced later, it will look
// like we're opening the file for the first time, and if we're set up to append to existing files it will cause and
// exception to be thrown, which is the desired result.
data.getFileStreamsCollection().closeOldestOpenFile( isZipFile );
}
if ( meta.isCreateParentFolder()
&& ( ( data.getFileStreamsCollection().size() == 0 ) || meta.isFileNameInField() ) ) {
createParentFolder( filename );
}
if ( log.isDetailed() ) {
logDetailed( "Opening output stream using provider: " + compressionProvider.getName() );View on GitHub (pinned to f3058517a1)