pentaho/pentaho-kettle · error · KettleException
JobGetMailsFromPOP.Error.AttachmentFolderNotAFolder
Error message
JobGetMailsFromPOP.Error.AttachmentFolderNotAFolder
What it means
Same check as the output-folder variant but for FOLDER_ATTACHMENTS: if the resolved attachments folder path exists on the VFS but is not a directory (FileType != FOLDER), this KettleException is thrown with the folder name as a parameter. The entry cannot write attachments into a non-directory.
Solutions
- Move/delete the file occupying the configured attachments path so a directory can be used there.
- Correct the 'Attachments directory' field to reference a directory path.
- Verify variable substitution output resolves to a directory, not a file path.
Example fix
// before attachments dir = /data/attachments.zip (file) // after attachments dir = /data/attachments (directory)
Defensive patterns
Strategy: validation
Validate before calling
File att = new File(environmentSubstitute(getAttachmentFolder()));
if (att.exists() && !att.isDirectory()) {
throw new IllegalArgumentException("Attachments path exists but is not a directory: " + att);
} Try / catch
try { executeJobEntry(); } catch (KettleException e) {
if (e.getMessage().contains("AttachmentFolderNotAFolder")) {
logError("Configured attachments path is a file, not a directory: " + e.getMessage());
} else { throw e; }
} Prevention
- Verify the attachments path is a directory on the executing host before scheduling.
- Avoid paths whose last segment could collide with generated files.
- Resolve and print substituted variables during development.
When it happens
Trigger: createOutputDirectory(FOLDER_ATTACHMENTS) with folder.exists() true and folder.getType() != FileType.FOLDER — the attachments path resolves to an existing regular file.
Common situations: Attachments directory points at an existing file; a mis-typed path like /data/attach.tar where /data/attach was intended; variable expansion appends a filename instead of a directory name.
Related errors
- JobGetMailsFromPOP.Error.NotAFolderNot
- JobGetMailsFromPOP.Error.AttachmentFolderEmpty
- JobGetMailsFromPOP.Error.AttachmentFolderNotExist
- JobGetMailsFromPOP.Error.OutputFolderEmpty
- JobGetMailsFromPOP.Error.OutputFolderNotExist
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/a125c99f6824c90e.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/email-messages/impl/src/main/java/org/pentaho/di/job/entries/getpop/JobEntryGetPOP.java:1593
break;
}
if ( Utils.isEmpty( folderName ) ) {
switch ( folderType ) {
case JobEntryGetPOP.FOLDER_OUTPUT:
throw new KettleException( BaseMessages.getString( PKG, "JobGetMailsFromPOP.Error.OutputFolderEmpty" ) );
case JobEntryGetPOP.FOLDER_ATTACHMENTS:
throw new KettleException( BaseMessages.getString( PKG, "JobGetMailsFromPOP.Error.AttachmentFolderEmpty" ) );
}
}
FileObject folder = KettleVFS.getInstance( parentJobMeta.getBowl() ).getFileObject( folderName, this );
if ( folder.exists() ) {
if ( folder.getType() != FileType.FOLDER ) {
switch ( folderType ) {
case JobEntryGetPOP.FOLDER_OUTPUT:
throw new KettleException( BaseMessages.getString(
PKG, "JobGetMailsFromPOP.Error.NotAFolderNot", folderName ) );
case JobEntryGetPOP.FOLDER_ATTACHMENTS:
throw new KettleException( BaseMessages.getString(
PKG, "JobGetMailsFromPOP.Error.AttachmentFolderNotAFolder", folderName ) );
}
}
if ( isDebug() ) {
switch ( folderType ) {
case JobEntryGetPOP.FOLDER_OUTPUT:
logDebug( BaseMessages.getString( PKG, "JobGetMailsFromPOP.Log.OutputFolderExists", folderName ) );
break;
case JobEntryGetPOP.FOLDER_ATTACHMENTS:
logDebug( BaseMessages.getString( PKG, "JobGetMailsFromPOP.Log.AttachmentFolderExists", folderName ) );
break;
}
}
} else {
if ( isCreateLocalFolder() ) {
folder.createFolder();
} else {
switch ( folderType ) {View on GitHub (pinned to f3058517a1)