pentaho/pentaho-kettle · error · ReportProcessingException

ReportExportTask.PARENT_FOLDER_DOES_NOT_EXIST

Error message

ReportExportTask.PARENT_FOLDER_DOES_NOT_EXIST

What it means

ReportExportTask.run() throws ReportProcessingException with ReportExportTask.PARENT_FOLDER_DOES_NOT_EXIST when createParentFolder is false and the target file's parent directory does not exist. The export task refuses to write the report because it has nowhere to put it; the failure is then reported via the status listener with USER_EXPORT_FAILED.

Solutions

  1. Enable the 'Create parent folder' option in the Pentaho Reporting Output step
  2. Create the target directory before running the transformation
  3. Use ${Internal.Transformation.Filename.Directory} or absolute paths to build a correct target directory
  4. Check variable values with a 'Get Variables' step or logging to confirm the resolved path

Example fix

// before
else if ( !targetFile.getParent().exists() ) {
  throw new ReportProcessingException(...);
}
// after — caller-side alternative: always create parents
exportTask.setCreateParentFolder( true ); // checkbox: Create parent folder
Defensive patterns

Strategy: validation

Validate before calling

FileObject target = KettleVFS.getInstance( bowl ).getFileObject( targetPath );
FileObject parent = target.getParent();
if ( !parent.exists() ) {
  parent.createFolder(); // or fail fast with a clear message
}

Try / catch

try {
  exportTask.run();
} catch ( ReportProcessingException e ) {
  if ( e.getMessage().contains( "PARENT_FOLDER_DOES_NOT_EXIST" ) ) {
    logError( "Missing output folder for " + targetPath );
  }
}

Prevention

When it happens

Trigger: createParentFolder flag unchecked in the step and targetFile.getParent().exists() returns false at run() time, right before execute().

Common situations: Target filename includes a directory that was never created (e.g. /out/reports/report.pdf with /out/reports missing); variable substitution produced a wrong base path; job changed working directory relative to a relative target path.

Related errors


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

Appendix: source

Thrown at plugins/pentaho-reporting/impl/src/main/java/org/pentaho/di/trans/steps/pentahoreporting/ReportExportTask.java:83

   * the object's <code>run</code> method to be called in that separately executing thread.
   * <p/>
   * The general contract of the method <code>run</code> is that it may take any action whatsoever.
   *
   * @see Thread#run()
   */
  public void run() {
    try {
      targetFile = KettleVFS.getInstance( bowl ).getFileObject( targetPath );
      if ( targetFile.exists() ) {
        if ( !targetFile.delete() ) {
          throw new ReportProcessingException( BaseMessages.getString( PKG, "ReportExportTask.ERROR_0001_TARGET_EXISTS" ) );
        }
      }

      if ( createParentFolder ) {
        targetFile.getParent().createFolder();
      } else if ( !targetFile.getParent().exists() ) {
        throw new ReportProcessingException( BaseMessages.getString( PKG,
          "ReportExportTask.PARENT_FOLDER_DOES_NOT_EXIST", targetFile.getParent().getName().getPath() ) );
      }

      execute();
    } catch ( Exception ex ) {
      statusListener.setStatus( StatusType.ERROR, BaseMessages.getString( PKG,  "ReportExportTask.USER_EXPORT_FAILED" ), ex );
      logger.error( BaseMessages.getString( PKG, "ReportExportTask.ERROR.GenerationFailed", targetPath ) );
    }
  }

  protected void execute() throws Exception {
    BufferedOutputStream fout = null;
    ReportProcessor reportProcessor = null;
    try {
      fout = new BufferedOutputStream( targetFile.getContent().getOutputStream() );
      reportProcessor = createReportProcessor( fout );
      reportProcessor.processReport();
      statusListener.setStatus( StatusType.INFORMATION, BaseMessages.getString( PKG, "ReportExportTask.USER_EXPORT_COMPLETE" ), 

View on GitHub (pinned to f3058517a1)