pentaho/pentaho-kettle · error · IOException

KettleVFS.Exception.ParentDirectoryDoesNotExist

KettleVFS.Exception.ParentDirectoryDoesNotExist

Error message

KettleVFS.Exception.ParentDirectoryDoesNotExist

What it means

KettleVFSImpl.getOutputStream(FileObject, append) refuses to open an output stream when the file's parent directory does not exist, throwing an IOException with localized message KettleVFS.Exception.ParentDirectoryDoesNotExist (including the friendly parent URI). This is a pre-check to avoid creating orphan files or confusing failures in createFile().

Solutions

  1. Create the parent directory first: KettleVFS.createDirectory(parent) or parent.createFolder() on the FileObject.
  2. In jobs/transformations, add a 'Create a folder' step or pre-create the directory in the script that runs the job.
  3. Fix typos in the directory portion of the output path.
  4. For SFTP, verify the remote directory exists and the user has permission to create/write there.

Example fix

// before
OutputStream os = KettleVFS.getOutputStream(KettleVFS.getFileObject("file:///data/out/report.csv"), false);
// after
FileObject fo = KettleVFS.getFileObject("file:///data/out/report.csv");
FileObject parent = fo.getParent();
if (parent != null && !parent.exists()) parent.createFolder();
OutputStream os = KettleVFS.getOutputStream(fo, false);
Defensive patterns

Strategy: validation

Validate before calling

FileObject parent = fo.getParent();
if (parent != null && !parent.exists()) parent.createFolder(); // ensure directory before writing

Try / catch

try (OutputStream os = KettleVFS.getOutputStream(fo, false)) {
  // write
} catch (IOException e) {
  if (e.getMessage().contains("ParentDirectoryDoesNotExist")) {
    fo.getParent().createFolder();
    // retry write once
  } else throw e;
}

Prevention

When it happens

Trigger: Calling KettleVFS.getOutputStream / fileObject content write where the target directory hasn't been created yet — e.g. writing to /data/out/report.csv when /data/out is missing, or sftp paths whose remote directory doesn't exist.

Common situations: Job writes to a dated output folder (e.g. /out/2026/09/13) nobody created; remote SFTP upload directory missing; typo in the directory part of the path; environment change where a mounted directory isn't present.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/150754a5444d0b93. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/vfs/KettleVFSImpl.java:326

  }

  @Override
  public InputStream getInputStream( String vfsFilename, VariableSpace space ) throws KettleFileException {
    try {
      FileObject fileObject = getFileObject( vfsFilename, space );

      return KettleVFS.getInputStream( fileObject );
    } catch ( IOException e ) {
      throw new KettleFileException( e );
    }
  }

  @Override
  public OutputStream getOutputStream( FileObject fileObject, boolean append ) throws IOException {
    FileObject parent = fileObject.getParent();
    if ( parent != null ) {
      if ( !parent.exists() ) {
        throw new IOException( BaseMessages.getString(
          PKG, "KettleVFS.Exception.ParentDirectoryDoesNotExist", KettleVFS.getFriendlyURI( parent ) ) );
      }
    }
    try {
      fileObject.createFile();
      FileContent content = fileObject.getContent();
      return content.getOutputStream( append );
    } catch ( FileSystemException e ) {
      // Perhaps if it's a local file, we can retry using the standard
      // File object. This is because on Windows there is a bug in VFS.
      //
      if ( fileObject instanceof LocalFile ) {
        try {
          String filename = KettleVFS.getFilename( fileObject );
          return new FileOutputStream( new File( filename ), append );
        } catch ( Exception e2 ) {
          throw e; // throw the original exception: hide the retry.
        }

View on GitHub (pinned to f3058517a1)