pentaho/pentaho-kettle · error · KettleException
Error opening new file
Error message
Error opening new file : {exception} What it means
isFileExists wraps any failure from the VFS file object's exists() check (getFileObject(filename, getTransMeta()).exists()) in a KettleException with this message. It means the file system layer could not even probe the file, not that the file exists or not. The underlying VFS/KettleVFS exception is flattened into e.toString(), so diagnose from that string.
Solutions
- Check e.toString() in the message to identify the underlying VFS error (malformed URI, permission, unknown host)
- Verify the fully substituted filename is a valid path (resolve variables before the run)
- Ensure the output directory exists and the process user has write permission
- Test the path scheme (file:, sftp:, etc.) is supported by the configured VFS provider
Example fix
// before
String filename = "${OUT_DIR}/export.txt"; // OUT_DIR unset -> invalid VFS url
// after
String filename = variables.getVariable( "OUT_DIR", "/data/out" ) + "/export.txt"; Defensive patterns
Strategy: validation
Validate before calling
String resolved = space.environmentSubstitute( filename );
if ( resolved == null || resolved.trim().isEmpty() ) {
throw new IllegalArgumentException( "Output filename resolves to empty" );
}
File dir = new File( new File( resolved ).getParent() );
if ( !dir.isDirectory() || !dir.canWrite() ) {
throw new IllegalArgumentException( "Output dir missing or unwritable: " + dir );
} Try / catch
try {
boolean exists = isFileExists( filename );
} catch ( KettleException e ) {
logError( "Cannot probe file " + filename + ": " + e.getMessage(), e );
// fall back to treating the file as absent or fail fast based on policy
} Prevention
- Verify all variables in the file path are defined before running the transformation
- Ensure target directories exist and are writable by the service account
- Test VFS schemes (sftp:, etc.) connectivity out-of-band before batch runs
When it happens
Trigger: Calling isFileExists (directly or via initFileStreamWriter/isWriteHeader) with a filename that resolves to an invalid/unreachable VFS URI, a permission-restricted path, or a malformed variable-expanded path (e.g. ${Internal.Transformation.Filename.Directory} unset).
Common situations: Output directory does not exist on a remote VFS (SFTP/HTTP) provider; environment variable in the file path not set at runtime; permission denied on the target directory; invalid Windows/UNC path syntax after variable substitution.
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
- ex.getMessage()
- GroupBy.Exception.UnableToCreateTemporaryFile
- KettleException(e)
- The function call getFileExtension throw an error :
- The function call getFileSize throw an error :
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a1b64a9e449ebe14.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/textfileoutput/TextFileOutput.java:92
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
}
private void initFieldNumbers( RowMetaInterface outputRowMeta, TextFileField[] outputFields ) throws KettleException {
data.fieldnrs = new int[outputFields.length];
for ( int i = 0; i < outputFields.length; i++ ) {
data.fieldnrs[i] = outputRowMeta.indexOfValue( outputFields[i].getName() );
if ( data.fieldnrs[i] < 0 ) {
throw new KettleStepException( "Field [" + outputFields[i].getName()
+ "] couldn't be found in the input stream!" );
}
}
}
public boolean isFileExists( String filename ) throws KettleException {
try {
return getFileObject( filename, getTransMeta() ).exists();
} catch ( Exception e ) {
throw new KettleException( "Error opening new file : " + e.toString() );
}
}
private CompressionProvider getCompressionProvider() throws KettleException {
String compressionType = Const.NVL( meta.getFileCompression(), FILE_COMPRESSION_TYPE_NONE );
CompressionProvider compressionProvider = CompressionProviderFactory.getInstance().getCompressionProviderByName( compressionType );
if ( compressionProvider == null ) {
throw new KettleException( "No compression provider found with name = " + compressionType );
}
if ( !compressionProvider.supportsOutput() ) {
throw new KettleException( "Compression provider " + compressionType + " does not support output streams!" );
}
return compressionProvider;
}
View on GitHub (pinned to f3058517a1)