pentaho/pentaho-kettle · error · KettleException
Can't encode object of class : className
Error message
Can't encode object of class : className
What it means
encodeAttributeValue only supports String, Double, Long/Integer, and Boolean objects; any other class (Date, BigDecimal, maps, POJOs) throws KettleException "Can't encode object of class ...". The metastore attribute store has a fixed value type set.
Solutions
- Convert unsupported objects before storing: use toString()/ISO-8601 for Date, toPlainString() for BigDecimal
- Encode as String and decode on read in your application code
- Restrict element attributes to the supported types (String, Double, Long/Integer, Boolean)
- Reject unsupported types at your API boundary with a clear validation error
Example fix
// before
attributes.put("created", new Date()); // throws
element.setProperty("created", attributes.get("created"));
// after
element.setProperty("created", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date())); Defensive patterns
Strategy: type-guard
Validate before calling
boolean encodable(Object v) { return v == null || v instanceof String || v instanceof Double || v instanceof Long || v instanceof Integer || v instanceof Boolean; } Type guard
Object coerceEncodable(Object v) {
if (v instanceof java.util.Date) return new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format((java.util.Date) v);
if (v instanceof java.math.BigDecimal) return ((java.math.BigDecimal) v).toPlainString();
return v;
} Try / catch
try { delegate.encodeAttributeValue(obj); } catch (KettleException e) { logError("Unsupported metastore attribute type: " + obj.getClass(), e); } Prevention
- Limit metastore element properties to String/Double/Long/Integer/Boolean
- Convert Dates and BigDecimals to strings before storing
- Add a boundary validator that rejects non-encodable attribute values early
When it happens
Trigger: Calling encodeAttributeValue (via insertAttributes when saving a metastore element) with an attribute value that is not String, Double, Long, Integer, or Boolean.
Common situations: Putting Date or BigDecimal values into a metastore element; framework code storing arbitrary objects in element properties; API change returning a boxed type different from what was stored before.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unable to parse attribute from attribute row: attributeRow
- Unknown data type : type
- AuthenticationManager.ConsumedTypeError
- AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint
- BaseStep.SafeMode.Exception.MixingTypes
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/995ae322e903ac2f.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/kdr/delegates/KettleDatabaseRepositoryMetaStoreDelegate.java:421
}
if ( object instanceof Timestamp ) {
return "T:" + new SimpleTimestampFormat(
ValueMetaBase.DEFAULT_TIMESTAMP_FORMAT_MASK ).format( (Timestamp) object );
}
if ( object instanceof Date ) {
return "D:" + new SimpleDateFormat( ValueMetaBase.DEFAULT_DATE_FORMAT_MASK ).format( (Date) object );
}
if ( object instanceof Double ) {
return "N:" + Double.toString( (Double) object );
}
if ( object instanceof Long ) {
return "I:" + Long.toString( (Long) object );
}
if ( object instanceof Boolean ) {
return "B:" + ( ( (Boolean) object ) ? "true" : "false" );
}
throw new KettleException( "Can't encode object of class : " + object.getClass().getName() );
}
public ObjectId insertElement( IMetaStoreElementType elementType, IMetaStoreElement element ) throws MetaStoreException {
try {
LongObjectId elementId =
repository.connectionDelegate.getNextID(
quoteTable( KettleDatabaseRepository.TABLE_R_ELEMENT ),
quote( KettleDatabaseRepository.FIELD_ELEMENT_ID_ELEMENT ) );
RowMetaAndData table = new RowMetaAndData();
table.addValue( new ValueMetaInteger(
KettleDatabaseRepository.FIELD_ELEMENT_ID_ELEMENT ), elementId
.longValue() );
table.addValue( new ValueMetaInteger(
KettleDatabaseRepository.FIELD_ELEMENT_ID_ELEMENT_TYPE ), Long
.valueOf( elementType.getId() ) );
table.addValue(View on GitHub (pinned to f3058517a1)