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
- 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>)).
- Check filesystem permissions for the user running the transformation (ls -ld on the target directory; chmod/chown as needed).
- Confirm all ${VARIABLES} in the data file path resolve correctly at runtime (check the log for the resolved path in the chained cause).
- Check disk space and that the mount is not read-only (df -h; touch <path> as the same user).
- 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
- Create the data file's parent directories in the transformation (or pre-create them at deployment).
- Run the transformation under a user with write access to the configured directory.
- Use absolute paths or verify all ${variables} resolve before running (test with 'Get Variables' preview).
- Monitor disk space on the volume holding the data file.
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
- Cannot open control file
- Cannot pipe content of control file to fastload
- CubeInputMeta.Exception.ErrorOpeningOrReadingCubeFile
- Error while setup
- TeraFast.Exception.TypeNotSupported
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)