pentaho/pentaho-kettle · error · KettleException
ex.getMessage()
Error message
ex.getMessage()
What it means
createControlFile wraps control-file creation and writing in try/catch; when the JVM throws an IOException (createNewFile, FileWriter, or write fail), it is rethrown as a KettleException whose message is the IOException's message and which keeps the original as the cause. Typical underlying causes are filesystem problems, not configuration.
Solutions
- Check the exception's cause chain (KettleException.getCause()) for the exact IOException.
- Verify the parent directory of the control-file path exists and is writable by the PDI process user.
- Create missing directories or correct the control-file path in the step dialog.
- Check free disk space and mount/permission policies (chmod, SELinux, container volumes).
Example fix
// before: writing to a directory that does not exist -> IOException
meta.setControlFile("/nonexistent/dir/load.ctl");
// after
new File("/data/gpload").mkdirs(); // ensure directory exists & is writable
meta.setControlFile("/data/gpload/load.ctl"); Defensive patterns
Strategy: try-catch
Validate before calling
File ctl = new File(meta.getControlFile().trim());
File parent = ctl.getAbsoluteFile().getParentFile();
if (parent == null || !parent.isDirectory() || !parent.canWrite()) {
throw new IllegalArgumentException("Control file directory missing or not writable: " + parent);
} Try / catch
try {
step.createControlFile(meta);
} catch (KettleException e) {
Throwable cause = e.getCause();
if (cause instanceof java.io.IOException) {
// inspect cause.getMessage() for permission/disk/path issues, then retry or abort
} else throw e;
} Prevention
- Ensure the control-file directory exists (mkdirs) before the transformation runs.
- Run PDI as a user with write permission on the target directory.
- Monitor disk space on servers executing GPLoad steps.
- Unwrap KettleException.getCause() when logging to see the real IOException.
When it happens
Trigger: controlFile.createNewFile(), new FileWriter(controlFile), or fw.write(...) throws IOException — e.g. the target directory does not exist, permission is denied, disk is full, or the path is a directory.
Common situations: Control-file path points to a read-only or nonexistent directory; the user running Pentaho lacks write permission; disk full on the PDI server; path is actually a directory; SELinux/container mount restrictions.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- ChangeFileEncoding.Error.CreatingFile
- Error opening new file
- Exporting jobs: Couldn't create file
- Exporting transformation: Couldn't create file
- GPLoad.Exception.DirectoryDoesNotExist
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/773acb7eb7d21d44.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/gpload/core/src/main/java/org/pentaho/di/trans/steps/gpload/GPLoad.java:418
String filename = meta.getControlFile();
if ( Utils.isEmpty( filename ) ) {
throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.NoControlFileSpecified" ) );
} else {
filename = environmentSubstitute( filename ).trim();
if ( Utils.isEmpty( filename ) ) {
throw new KettleException( BaseMessages.getString( PKG, "GPLoad.Exception.NoControlFileSpecified" ) );
}
}
File controlFile = new File( filename );
FileWriter fw = null;
try {
controlFile.createNewFile();
fw = new FileWriter( controlFile );
fw.write( getControlFileContents( meta, getInputRowMeta() ) );
} catch ( IOException ex ) {
throw new KettleException( ex.getMessage(), ex );
} finally {
try {
if ( fw != null ) {
fw.close();
}
} catch ( Exception ignored ) {
// Ignore error
}
}
}
/**
* Returns the path to the pathToFile. It should be the same as what was passed but this method will check the file
* system to see if the path is valid.
*
* @param pathToFile
* Path to the file to verify.
* @param exceptionMessageView on GitHub (pinned to f3058517a1)