pentaho/pentaho-kettle · error · KettleException

Cannot open data file

Error message

Cannot open data file [path=${dataFile}]

What it means

TeraFast throws this KettleException in processRow (first row) when FileUtils.openOutputStream cannot open the resolved data file for writing; the IOException is chained as the cause. The data file is the intermediate file TeraFast writes row data to before Teradata FastLoad consumes it. If it cannot be created/opened, the bulk load cannot proceed.

Solutions

  1. Verify the Data file property in the TeraFast step resolves to a valid, writable file path (create parent directories, e.g. mkdir -p $(dirname <path>)).
  2. Check filesystem permissions for the user running the transformation (ls -ld on the target directory; chmod/chown as needed).
  3. Confirm all ${VARIABLES} in the data file path resolve correctly at runtime (check the log for the resolved path in the chained cause).
  4. Check disk space and that the mount is not read-only (df -h; touch <path> as the same user).
  5. If the path exists as a directory, remove/rename it or choose a different filename.

Example fix

// before
this.dataFile = FileUtils.openOutputStream( new File( this.meta.getDataFile().getValue() ) );
// after
File tempDataFile = new File( resolveFileName( this.meta.getDataFile().getValue() ) );
java.io.File parent = tempDataFile.getParentFile();
if ( parent != null && !parent.exists() ) {
  parent.mkdirs(); // ensure the target directory exists before opening the stream
}
this.dataFile = FileUtils.openOutputStream( tempDataFile );
Defensive patterns

Strategy: validation

Validate before calling

import java.io.File;
File dataFile = new File( resolveFileName( dataFileValue ) );
File parent = dataFile.getParentFile();
if ( parent == null || !parent.isDirectory() || !parent.canWrite() ) {
  throw new IllegalArgumentException( "Data file directory missing or unwritable: " + parent );
}
if ( dataFile.isDirectory() ) {
  throw new IllegalArgumentException( "Data file path is a directory: " + dataFile );
}

Type guard

boolean isWritableFilePath( String path ) {
  File f = new File( path );
  return f.getParentFile() != null && f.getParentFile().isDirectory()
    && f.getParentFile().canWrite() && !f.isDirectory();
}

Try / catch

try {
  this.dataFile = FileUtils.openOutputStream( tempDataFile );
} catch ( IOException e ) {
  throw new KettleException( "Cannot open data file [path=" + tempDataFile.getAbsolutePath()
    + "]; check directory exists, permissions, and disk space", e );
}

Prevention

When it happens

Trigger: First call to processRow() after init: resolveFileName(meta.getDataFile().getValue()) yields a path in a non-existent directory, an unwritable location, a path that is a directory, or the filesystem rejects creation (disk full, permissions).

Common situations: Data file path points to a directory that doesn't exist; user running Kettle lacks write permission on the target folder; the path was configured with a variable that resolves to an invalid/empty value; path is on a full or read-only mount; a directory already exists with the same name as the intended file.

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/73e40a14f1f3f667. Report an issue: GitHub.

Appendix: source

Thrown at plugins/terafast-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/terafastbulkloader/TeraFast.java:207

          logBasic( BaseMessages.getString( PKG, "TeraFast.Log.ExitValueFastloadPath", "" + exitVal ) );
        }
      } catch ( Exception e ) {
        logError( BaseMessages.getString( PKG, "TeraFast.Log.ErrorInStep" ), e );
        this.setDefaultError();
        stopAll();
      }

      return false;
    }

    if ( this.first ) {
      this.first = false;
      try {
        final File tempDataFile = new File( resolveFileName( this.meta.getDataFile().getValue() ) );
        this.dataFile = FileUtils.openOutputStream( tempDataFile );
        this.dataFilePrintStream = new PrintStream( dataFile );
      } catch ( IOException e ) {
        throw new KettleException( "Cannot open data file [path=" + this.dataFile + "]", e );
      }

      // determine column sort order according to field mapping
      // thus the columns in the generated datafile are always in the same order and have the same size as in the
      // targetTable
      this.tableRowMeta = this.meta.getRequiredFields( this.getTransMeta() );
      RowMetaInterface streamRowMeta = this.getTransMeta().getPrevStepFields( this.getStepMeta() );
      this.columnSortOrder = new ArrayList<>( this.tableRowMeta.size() );
      for ( int i = 0; i < this.tableRowMeta.size(); i++ ) {
        ValueMetaInterface column = this.tableRowMeta.getValueMeta( i );
        int tableIndex = this.meta.getTableFieldList().getValue().indexOf( column.getName() );
        if ( tableIndex >= 0 ) {
          String streamField = this.meta.getStreamFieldList().getValue().get( tableIndex );
          this.columnSortOrder.add( streamRowMeta.indexOfValue( streamField ) );
        }
      }
    }

View on GitHub (pinned to f3058517a1)