pentaho/pentaho-kettle · error · KettleException

Error opening new file

Error message

Error opening new file : {exception}

What it means

isFileExists wraps any failure from the VFS file object's exists() check (getFileObject(filename, getTransMeta()).exists()) in a KettleException with this message. It means the file system layer could not even probe the file, not that the file exists or not. The underlying VFS/KettleVFS exception is flattened into e.toString(), so diagnose from that string.

Solutions

  1. Check e.toString() in the message to identify the underlying VFS error (malformed URI, permission, unknown host)
  2. Verify the fully substituted filename is a valid path (resolve variables before the run)
  3. Ensure the output directory exists and the process user has write permission
  4. Test the path scheme (file:, sftp:, etc.) is supported by the configured VFS provider

Example fix

// before
String filename = "${OUT_DIR}/export.txt"; // OUT_DIR unset -> invalid VFS url
// after
String filename = variables.getVariable( "OUT_DIR", "/data/out" ) + "/export.txt";
Defensive patterns

Strategy: validation

Validate before calling

String resolved = space.environmentSubstitute( filename );
if ( resolved == null || resolved.trim().isEmpty() ) {
  throw new IllegalArgumentException( "Output filename resolves to empty" );
}
File dir = new File( new File( resolved ).getParent() );
if ( !dir.isDirectory() || !dir.canWrite() ) {
  throw new IllegalArgumentException( "Output dir missing or unwritable: " + dir );
}

Try / catch

try {
  boolean exists = isFileExists( filename );
} catch ( KettleException e ) {
  logError( "Cannot probe file " + filename + ": " + e.getMessage(), e );
  // fall back to treating the file as absent or fail fast based on policy
}

Prevention

When it happens

Trigger: Calling isFileExists (directly or via initFileStreamWriter/isWriteHeader) with a filename that resolves to an invalid/unreachable VFS URI, a permission-restricted path, or a malformed variable-expanded path (e.g. ${Internal.Transformation.Filename.Directory} unset).

Common situations: Output directory does not exist on a remote VFS (SFTP/HTTP) provider; environment variable in the file path not set at runtime; permission denied on the target directory; invalid Windows/UNC path syntax after variable substitution.

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


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/a1b64a9e449ebe14. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/textfileoutput/TextFileOutput.java:92

    super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
  }

  private void initFieldNumbers( RowMetaInterface outputRowMeta, TextFileField[] outputFields ) throws KettleException {
    data.fieldnrs = new int[outputFields.length];
    for ( int i = 0; i < outputFields.length; i++ ) {
      data.fieldnrs[i] = outputRowMeta.indexOfValue( outputFields[i].getName() );
      if ( data.fieldnrs[i] < 0 ) {
        throw new KettleStepException( "Field [" + outputFields[i].getName()
          + "] couldn't be found in the input stream!" );
      }
    }
  }

  public boolean isFileExists( String filename ) throws KettleException {
    try {
      return getFileObject( filename, getTransMeta() ).exists();
    } catch ( Exception e ) {
      throw new KettleException( "Error opening new file : " + e.toString() );
    }
  }

  private CompressionProvider getCompressionProvider() throws KettleException {
    String compressionType = Const.NVL( meta.getFileCompression(), FILE_COMPRESSION_TYPE_NONE );

    CompressionProvider compressionProvider = CompressionProviderFactory.getInstance().getCompressionProviderByName( compressionType );

    if ( compressionProvider == null ) {
      throw new KettleException( "No compression provider found with name = " + compressionType );
    }

    if ( !compressionProvider.supportsOutput() ) {
      throw new KettleException( "Compression provider " + compressionType + " does not support output streams!" );
    }
    return compressionProvider;
  }

View on GitHub (pinned to f3058517a1)