pentaho/pentaho-kettle · error · KettleException
JobGetMailsFromPOP.Error.AttachmentFolderEmpty
Error message
JobGetMailsFromPOP.Error.AttachmentFolderEmpty
What it means
createOutputDirectory(FOLDER_ATTACHMENTS) throws this KettleException when the resolved attachments folder path is empty. Attachments extracted from fetched mails need a target directory; an empty one aborts the entry before any mail is processed.
Solutions
- Fill in the 'Attachments directory' field with a valid absolute path.
- Define any variable used for the attachments directory before the job runs.
- Disable attachment saving (uncheck include attachments) if attachments are not needed, so the field is irrelevant.
Example fix
// before (kjb XML) <attachment_folder></attachment_folder> // after <attachment_folder>/data/pentaho/mail_attachments</attachment_folder>
Defensive patterns
Strategy: validation
Validate before calling
String att = environmentSubstitute(getAttachmentFolder());
if (includeAttachments() && (att == null || att.trim().isEmpty())) {
throw new IllegalArgumentException("Attachments folder must be set when saving attachments");
} Try / catch
try { executeJobEntry(); } catch (KettleException e) {
if (e.getMessage().contains("AttachmentFolderEmpty")) {
logError("Attachments directory is empty; set attachment_folder or disable attachment saving");
} else { throw e; }
} Prevention
- Fill the attachments directory whenever attachment saving is enabled.
- Define attachment-folder variables in kettle.properties for all environments.
- Include a validation step/job before fetching mail.
When it happens
Trigger: execute() -> createOutputDirectory(FOLDER_ATTACHMENTS) with Utils.isEmpty(folderName) true: the attachments directory field is blank or its variable resolves to empty string.
Common situations: 'Attachments directory' left blank even though 'include attachments' is selected; variable ${ATTACH_DIR} undefined at runtime; entry copied from a template where the field was cleared.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- JobGetMailsFromPOP.Error.OutputFolderEmpty
- JobGetMailsFromPOP.Error.AttachmentFolderNotAFolder
- JobGetMailsFromPOP.Error.AttachmentFolderNotExist
- JobGetMailsFromPOP.Error.NotAFolderNot
- JobGetMailsFromPOP.Error.OutputFolderNotExist
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/94cf222382c4806c.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/email-messages/impl/src/main/java/org/pentaho/di/job/entries/getpop/JobEntryGetPOP.java:1582
String folderName = "";
switch ( folderType ) {
case JobEntryGetPOP.FOLDER_OUTPUT:
folderName = getRealOutputDirectory();
break;
case JobEntryGetPOP.FOLDER_ATTACHMENTS:
if ( isSaveAttachment() && isDifferentFolderForAttachment() ) {
folderName = getRealAttachmentFolder();
} else {
folderName = getRealOutputDirectory();
}
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 ) );View on GitHub (pinned to f3058517a1)