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

  1. Disable the 'Append' option in the Text File Output step, or delete/move the existing .zip file before running.
  2. Switch compression to None or GZip if appending is required (GZip supports append via stream concatenation).
  3. Add a preceding step/job entry that removes the existing file when present.
  4. 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

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


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)