pentaho/pentaho-kettle · error · KettleException
Cannot open control file
Error message
Cannot open control file [path=${controlFile}] What it means
invokeLoadingControlFile opens the fastload control file with FileUtils.openInputStream; an IOException there (file missing, unreadable, path is a directory) is wrapped as 'Cannot open control file [path=...]'. The control file holds the FastLoad script and must be readable before its content is piped to the running fastload process.
Solutions
- Verify the control file path resolves and exists: ls -l <resolved-path>; regenerate the control file if it was deleted.
- Fix variable substitution: log or print resolveFileName(meta.getControlFile().getValue()) and confirm the ${VARIABLE} values at runtime.
- Grant read permission on the control file and its parent directory to the Kettle run user.
- Confirm the path points to a file, not a directory, and uses OS-appropriate separators.
- If the control file is expected to be auto-generated by TeraFast, enable the generation option or run the prerequisite step first.
Example fix
// before
control = FileUtils.openInputStream( controlFile );
// after
if ( !controlFile.isFile() || !controlFile.canRead() ) {
throw new KettleException( "Control file missing or unreadable: " + controlFile.getAbsolutePath() ); // fail with actionable message
}
control = FileUtils.openInputStream( controlFile ); Defensive patterns
Strategy: validation
Validate before calling
import java.io.File; String resolved = resolveFileName( controlFileValue ); File cf = new File( resolved ); if ( !cf.exists() ) throw new IllegalStateException( "Control file does not exist: " + cf.getAbsolutePath() ); if ( !cf.isFile() ) throw new IllegalStateException( "Control file path is not a file: " + cf.getAbsolutePath() ); if ( !cf.canRead() ) throw new IllegalStateException( "Control file not readable by current user: " + cf.getAbsolutePath() );
Type guard
boolean isReadableFile( String path ) {
File f = new File( path );
return f.isFile() && f.canRead();
} Try / catch
try {
control = FileUtils.openInputStream( controlFile );
controlContent = environmentSubstitute( FileUtils.readFileToString( controlFile ) );
} catch ( IOException e ) {
throw new KettleException( "Cannot open control file [path=" + controlFile.getAbsolutePath()
+ "]; verify the file exists, is readable, and variables resolve correctly", e );
} Prevention
- Generate the control file in a prior step (or enable auto-generation) before invoking the load.
- Use absolute paths and verify ${variable} resolution with a variable preview.
- Ensure read permissions for the Kettle run user on the file and its directory.
- Avoid OS-specific separators; build paths with File/Paths APIs.
When it happens
Trigger: execute() -> invokeLoadingControlFile(): meta.getControlFile().getValue() resolves (after resolveFileName) to a non-existent file, a directory, or a file the current OS user cannot read, so FileUtils.openInputStream/readFileToString throws IOException.
Common situations: Control file was never generated (e.g. 'generate control file' option disabled but a path still configured); typo or wrong variable value in the control file path; file generated on another host/agent; permission tightened after generation; path uses Windows separators on Linux.
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 data 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/25849014d9a95356.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/terafast-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/terafastbulkloader/TeraFast.java:367
}
}
/**
* Invoke loading with control file.
*
* @throws KettleException
* ...
*/
private void invokeLoadingControlFile() throws KettleException {
File controlFile = null;
final InputStream control;
final String controlContent;
try {
controlFile = new File( resolveFileName( this.meta.getControlFile().getValue() ) );
control = FileUtils.openInputStream( controlFile );
controlContent = environmentSubstitute( FileUtils.readFileToString( controlFile ) );
} catch ( IOException e ) {
throw new KettleException( "Cannot open control file [path=" + controlFile + "]", e );
}
try {
IOUtils.write( controlContent, this.fastload );
this.fastload.flush();
} catch ( IOException e ) {
throw new KettleException( "Cannot pipe content of control file to fastload [path=" + controlFile + "]", e );
} finally {
IOUtils.closeQuietly( control );
IOUtils.closeQuietly( this.fastload );
}
}
/**
* Invoke loading with loading commands.
*
* @throws KettleException
* ...
*/View on GitHub (pinned to f3058517a1)