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
- Enable the 'Create parent folder' option in the Pentaho Reporting Output step
- Create the target directory before running the transformation
- Use ${Internal.Transformation.Filename.Directory} or absolute paths to build a correct target directory
- 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
- Enable 'Create parent folder' in the step settings
- Log resolved variables to verify the target directory path
- Create output directories in an earlier job entry
- Prefer absolute paths over relative ones in scheduled jobs
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
- AbstractFileErrorHandler.Exception.CouldNotCreateFileErrorHandlerForFile
- AvroInputDialog.Error.KettleFileException
- ConnectionFileSystem.ExpectedConnectionNotFound
- CustomVfsSettingsParser.Log.FailedToLoad
- ERROR_0001_TARGET_EXISTS
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)