pentaho/pentaho-kettle · error · KettleException
PGBulkLoader doesn't know how to handle date (neither…
Error message
PGBulkLoader doesn't know how to handle date (neither passthrough, nor date or datetime for field
What it means
When writing a row field of type Date to the COPY stream, writeRowToPostgres switches on data.dateFormatChoices[i]; the default branch fires when the date format choice is none of passthrough/date/datetime. This is an internal configuration mismatch for that field's date handling.
Solutions
- Open the step's Fields tab and explicitly set a Date format (Date mask) for every date field, then re-save
- Inspect the saved transformation/repo metadata for the field's date_mask value and correct it to a recognized value
- Recreate the field mapping with 'Get Fields' so defaults are applied cleanly
- Patch PGBulkLoaderMeta.readData/readRep handling so unknown masks fall back to a valid default instead of producing an unmapped choice
Example fix
// before (unmapped mask) dateMask[i] = "weird_mask"; // -> dateFormatChoices[i] hits default // after meta.setDateMask( i, PGBulkLoaderMeta.getDateMaskDefault() ); // recognized constant
Defensive patterns
Strategy: validation
Validate before calling
// verify each date field has a recognized mask in the saved meta
for ( int i = 0; i < meta.getFieldStream().length; i++ ) {
String mask = meta.getFieldDateMask()[i];
if ( mask == null || !List.of( "Pass through", "Date mask", "DateTime mask" ).contains( mask ) ) {
throw new IllegalStateException( "Unrecognized date mask for field " + meta.getFieldStream()[i] );
}
} Try / catch
try {
step.processRow();
} catch ( KettleException e ) {
if ( e.getMessage().contains( "doesn't know how to handle date" ) ) {
// reconfigure the date mask for the named field
}
} Prevention
- Explicitly set a Date mask for every date field in the Fields tab
- After version upgrades, re-save transformations to normalize stored masks
- Avoid hand-editing date_mask values in ktr XML
When it happens
Trigger: A field of ValueMetaInterface.TYPE_DATE reaches writeRowToPostgres while its entry in data.dateFormatChoices was never initialized to one of the supported choices (passthrough, date, datetime), e.g. meta loaded from an unrecognized/empty date_mask value.
Common situations: Older or hand-edited transformation XML where the date mask attribute is missing or has an unexpected value; repository record with a corrupted date_mask string; version upgrade changing the recognized mask constants so a stored value no longer maps to a choice.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- No fields defined to load to database
- PGBulkLoader doesn't know how to handle timestamp (neither…
- AccessInput.Exception.CouldnotFindField
- AccessInput.Log.NoField
- AddSequence.Exception.NoSpecifiedMethod
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/d2c18881ed0e3ad4.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/postgresql-db-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/pgbulkloader/PGBulkLoader.java:354
//
case PGBulkLoaderMeta.NR_DATE_MASK_DATE:
String dateString = data.dateMeta.getString( valueMeta.getDate( valueData ) );
if ( dateString != null ) {
pgCopyOut.write( dateString.getBytes( clientEncoding ) );
}
break;
// Convert to a "YYYY-MM-DD HH:MM:SS.mmm" format
//
case PGBulkLoaderMeta.NR_DATE_MASK_DATETIME:
String dateTimeString = data.dateTimeMeta.getString( valueMeta.getDate( valueData ) );
if ( dateTimeString != null ) {
pgCopyOut.write( dateTimeString.getBytes( clientEncoding ) );
}
break;
default:
throw new KettleException( "PGBulkLoader doesn't know how to handle date (neither passthrough, nor date or datetime for field " + valueMeta.getName() );
}
break;
case ValueMetaInterface.TYPE_TIMESTAMP:
// Format the date in the right format.
//
switch ( data.dateFormatChoices[i] ) {
// Pass the data along in the format chosen by the user OR in binary format...
//
case PGBulkLoaderMeta.NR_DATE_MASK_PASS_THROUGH:
if ( valueMeta.isStorageBinaryString() ) {
pgCopyOut.write( (byte[]) valueData );
} else {
String dateString = valueMeta.getString( valueData );
if ( dateString != null ) {
pgCopyOut.write( dateString.getBytes( clientEncoding ) );
}
}
break;View on GitHub (pinned to f3058517a1)