pentaho/pentaho-kettle · error · IOException
FixedInput.Log.OnlyLocalFilesAreSupported
FixedInput.Log.OnlyLocalFilesAreSupported
Error message
FixedInput.Log.OnlyLocalFilesAreSupported
What it means
The deprecated KettleVFS.getFileInputStream(FileObject) only works on local files because it relies on NIO FileInputStream; if the VFS FileObject is not a commons-vfs LocalFile (e.g. SFTP, HTTP, S3, or a compressed archive entry), it throws an IOException carrying the localized message key FixedInput.Log.OnlyLocalFilesAreSupported.
Solutions
- Copy/download the remote file to a local temp path first, then open it locally.
- Read the FileObject content generically: fileObject.getContent().getInputStream() instead of the deprecated method.
- Use KettleVFS.getInputStream(FileObject) / the non-deprecated API which supports any VFS scheme.
- If the file must be local, verify the filename has no scheme or archive prefix.
Example fix
// before
InputStream in = KettleVFS.getFileInputStream(KettleVFS.getFileObject("sftp://host/data.csv", space));
// after
InputStream in = KettleVFS.getInputStream(KettleVFS.getFileObject("sftp://host/data.csv", space)); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(fileObject instanceof org.apache.commons.vfs2.provider.local.LocalFile)) {
// use generic content input stream instead
} Type guard
boolean isLocalFile(FileObject fo) { return fo instanceof org.apache.commons.vfs2.provider.local.LocalFile; } Try / catch
try {
in = KettleVFS.getFileInputStream(fo);
} catch (IOException e) {
if (e.getMessage().contains("OnlyLocalFilesAreSupported")) {
in = fo.getContent().getInputStream(); // generic VFS fallback
} else throw e;
} Prevention
- Avoid the deprecated getFileInputStream; use KettleVFS.getInputStream for all schemes.
- Check the URI scheme before choosing an I/O strategy.
- Download remote files to a temp dir when NIO semantics are required.
When it happens
Trigger: Calling KettleVFS.getFileInputStream on a FileObject obtained from a non-local scheme (sftp://, http://, s3://, zip:..., etc.) — typically via the Fixed Input step or code reading a remote/virtual file with this legacy API.
Common situations: Migrating a transformation that previously read local files to a remote source; pointing the Fixed Input step at an SFTP or HDFS URL; passing an archive entry (zip:file:///x.zip!/inner.csv) where a plain local path was expected.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Append file in repository is not possible
- Cannot add converters
- ConnectionFileObject.ConnectionWithBucketsRoot.UnsupportedOperation
- ConnectionFileObject.PVFSRoot.UnsupportedOperation
- CsvInput.Log.OnlyLocalFilesAreSupported
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/2515df60bc95e1d0.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/vfs/KettleVFS.java:501
};
}
/**
* Get a FileInputStream for a local file. Local files can be read with NIO.
*
* @param fileObject
* @return a FileInputStream
* @throws IOException
* @deprecated because of API change in Apache VFS. As a workaround use FileObject.getName().getPathDecoded(); Then
* use a regular File() object to create a File Input stream.
*/
@Deprecated
public static FileInputStream getFileInputStream( FileObject fileObject ) throws IOException {
if ( !( fileObject instanceof LocalFile ) ) {
// We can only use NIO on local files at the moment, so that's what we limit ourselves to.
//
throw new IOException( BaseMessages.getString( PKG, "FixedInput.Log.OnlyLocalFilesAreSupported" ) );
}
return new FileInputStream( fileObject.getName().getPathDecoded() );
}
/**
* Check if filename starts with one of the known protocols like file: zip: ram: smb: jar: etc.
* If yes, return true otherwise return false
*
* @param vfsFileName
* @return boolean
*/
public static boolean startsWithScheme( String vfsFileName ) {
FileSystemManager fsManager = getInstance().getFileSystemManager();
boolean found = false;
String[] schemes = fsManager.getSchemes();
for (int i = 0; i < schemes.length; i++) {View on GitHub (pinned to f3058517a1)