pentaho/pentaho-kettle · error · ContentIOException

The given backend-file is not a directory.

Error message

The given backend-file is not a directory.

What it means

The FileObjectContentLocation constructor validates that the given VFS FileObject backend is an existing folder. If it does not exist or is not a folder, it throws ContentIOException("The given backend-file is not a directory."); FileSystemException during the check is rethrown as RuntimeException. This guards the URL report repository against being rooted at a file or a missing path.

Solutions

  1. Pre-create the directory used as the repository root before running the export
  2. Point the configuration at a directory, not a file path
  3. Fix the path/scheme typo in the URL repository configuration
  4. Wrap the check: if the backend is missing, create it (createFolder) before constructing the content location

Example fix

// before
FileObject repo = KettleVFS.getInstance( bowl ).getFileObject( path );
new FileObjectContentLocation( null, repo );
// after
FileObject repo = KettleVFS.getInstance( bowl ).getFileObject( path );
if ( !repo.exists() ) {
  repo.createFolder();
}
new FileObjectContentLocation( null, repo );
Defensive patterns

Strategy: validation

Validate before calling

FileObject backend = KettleVFS.getInstance( bowl ).getFileObject( repoPath );
if ( !backend.exists() ) backend.createFolder();
if ( !backend.isFolder() ) {
  throw new IllegalArgumentException( repoPath + " is not a directory" );
}

Type guard

boolean isValidRepoRoot( FileObject backend ) {
  try {
    return backend != null && backend.exists() && backend.isFolder();
  } catch ( FileSystemException e ) {
    return false;
  }
}

Try / catch

try {
  new FileObjectContentLocation( null, backend );
} catch ( ContentIOException e ) {
  logError( "Repository root invalid: " + backend.getName().getURI(), e );
}

Prevention

When it happens

Trigger: Constructing a FileObjectContentLocation with a backend that backend.exists()==false or backend.isFolder()==false — e.g. a path pointing at a regular file, or a non-existent directory passed as the repository root.

Common situations: Report output URL/repository configured with a file path instead of a directory; directory deleted before the export; typo in the repository root path so the folder never existed; VFS scheme mismatch (file vs. remote provider).

Related errors


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

Appendix: source

Thrown at plugins/pentaho-reporting/impl/src/main/java/org/pentaho/di/trans/steps/pentahoreporting/urlrepository/FileObjectContentLocation.java:54

  private static final long serialVersionUID = -5452372293937107734L;

  /**
   * Creates a new location for the given parent and directory.
   *
   * @param parent  the parent location.
   * @param backend the backend.
   * @throws ContentIOException if an error occured or the file did not point to a directory.
   */
  public FileObjectContentLocation( final ContentLocation parent, final FileObject backend ) throws ContentIOException {
    super( parent, backend );
    boolean error;
    try {
      error = backend.exists() == false || backend.isFolder() == false;
    } catch ( FileSystemException e ) {
      throw new RuntimeException( e );
    }
    if ( error ) {
      throw new ContentIOException( "The given backend-file is not a directory." );
    }
  }

  /**
   * Creates a new root-location for the given repository and directory.
   *
   * @param repository the repository for which a location should be created.
   * @param backend    the backend.
   * @throws ContentIOException if an error occured or the file did not point to a directory.
   */
  public FileObjectContentLocation( final Repository repository, final FileObject backend ) throws ContentIOException {
    super( repository, backend );
    boolean error;
    try {
      error = backend.exists() == false || backend.isFolder() == false;
    } catch ( FileSystemException e ) {
      throw new RuntimeException( e );
    }

View on GitHub (pinned to f3058517a1)