pentaho/pentaho-kettle · error · KettleException
No control file specified
Error message
No control file specified
What it means
sqlldr cannot run without a control file, so createCommandLine demands one: if meta.getControlFile() is null or empty after the sqlldr executable, this KettleException is thrown instead of appending control='...' to the command line.
Solutions
- Set the control file field in the step dialog to a path the step can write to, e.g. /tmp/orabulk/load.ctl.
- Ensure the target directory exists and the runtime user has write permission.
- Re-save and validate the transformation so the field persists in the ktr.
Example fix
// before <control_file/> // after <control_file>/tmp/orabulk/load.ctl</control_file>
Defensive patterns
Strategy: validation
Validate before calling
// Java: verify a control file location is configured before execution
if (meta.getControlFile() == null || meta.getControlFile().trim().isEmpty()) {
throw new IllegalArgumentException(
"Oracle Bulk Loader: control file path is required, e.g. /tmp/orabulk/load.ctl");
} Try / catch
try {
trans.execute(null);
} catch (KettleException e) {
if (String.valueOf(e.getMessage()).contains("No control file specified")) {
// guide user to set the control file field in the step dialog
}
} Prevention
- Always fill both sqlldr and control file fields when configuring the step.
- Validate step configuration programmatically before scheduling transformations.
- Keep a template ktr with required loader fields pre-filled.
When it happens
Trigger: meta.getControlFile() == null when createCommandLine is invoked from execute — the control file name/directory field is blank in the step settings.
Common situations: User assumed the step auto-generates and auto-names the control file location but left the field empty; configuration exported/imported and the field lost; running headless with a ktr whose step config is incomplete.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Error retrieving controlfile string
- No connection specified
- No control file specified
- No sqlldr application specified
- OraBulkLoaderMeta.Exception.ConnectionNotDefined
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/6f66213e8f783cca.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/oracle-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/orabulkloader/OraBulkLoader.java:373
throw new KettleException( "Error retrieving sqlldr string", ex );
}
} else {
throw new KettleException( "No sqlldr application specified" );
}
if ( meta.getControlFile() != null ) {
try {
FileObject fileObject =
getFileObject( meta.getControlFile(), getTransMeta() );
sb.append( " control=\'" );
sb.append( getFilename( fileObject ) );
sb.append( "\'" );
} catch ( KettleFileException ex ) {
throw new KettleException( "Error retrieving controlfile string", ex );
}
} else {
throw new KettleException( "No control file specified" );
}
if ( OraBulkLoaderMeta.METHOD_AUTO_CONCURRENT.equals( meta.getLoadMethod() ) ) {
sb.append( " data=\'-\'" );
}
if ( meta.getLogFile() != null ) {
try {
FileObject fileObject =
getFileObject( meta.getLogFile(), getTransMeta() );
sb.append( " log=\'" );
sb.append( getFilename( fileObject ) );
sb.append( "\'" );
} catch ( KettleFileException ex ) {
throw new KettleException( "Error retrieving logfile string", ex );
}
}View on GitHub (pinned to f3058517a1)