pentaho/pentaho-kettle · error · KettleValueException
Unknown source type:
Error message
Unknown source type:
What it means
RowMetaAndData.isEmptyValue() checks whether the value at an index is null for a known Kettle value type. If the row's value meta type is not one of the handled types (String, Number, Integer, Date, Timestamp, InetAddress, Boolean, etc.), it throws this KettleValueException including getTypeDesc(). It guards against silently misinterpreting nullness for unsupported types.
Solutions
- Inspect the field's value meta type and convert it to a supported type (e.g. String or Integer) before injecting
- Change the step configuration so the injected field uses a standard Kettle value type
- Catch KettleValueException and log the offending field name/type
- Upgrade Pentaho/Kettle, since newer versions may handle more types
Example fix
// before rowMeta.setValueMeta(idx, new ValueMetaBinary(field)); // after rowMeta.setValueMeta(idx, new ValueMetaString(field));
Defensive patterns
Strategy: try-catch
Validate before calling
int idx = row.getRowMeta().indexOfValue(fieldName);
ValueMetaInterface vm = row.getRowMeta().getValueMeta(idx);
switch (vm.getType()) {
case ValueMetaInterface.TYPE_STRING:
case ValueMetaInterface.TYPE_NUMBER:
case ValueMetaInterface.TYPE_INTEGER:
case ValueMetaInterface.TYPE_BOOLEAN:
case ValueMetaInterface.TYPE_DATE:
case ValueMetaInterface.TYPE_TIMESTAMP:
case ValueMetaInterface.TYPE_INET:
break; // safe
default:
throw new IllegalStateException("Unsupported type for isEmptyValue: " + vm.getTypeDesc());
} Type guard
boolean isSupportedType(ValueMetaInterface vm) {
int t = vm.getType();
return t == ValueMetaInterface.TYPE_STRING || t == ValueMetaInterface.TYPE_NUMBER
|| t == ValueMetaInterface.TYPE_INTEGER || t == ValueMetaInterface.TYPE_BOOLEAN
|| t == ValueMetaInterface.TYPE_DATE || t == ValueMetaInterface.TYPE_TIMESTAMP
|| t == ValueMetaInterface.TYPE_INET;
} Try / catch
try {
boolean empty = row.isEmptyValue(idx);
} catch (KettleValueException e) {
log.error("Unsupported value type for field " + row.getRowMeta().getValueMeta(idx).getTypeDesc(), e);
} Prevention
- Only inject standard Kettle value types (String, Integer, Number, Boolean, Date, Timestamp, InetAddress)
- Check ValueMetaInterface.getType() against supported types before calling setProperty/createAvroRecord
- Convert exotic types (Binary, Serializable) to String upstream
When it happens
Trigger: Calling isEmptyValue (directly or via setProperty / createAvroRecord during metadata injection) when the field's ValueMetaInterface type is not covered by the switch, e.g. a Binary, Serializable, or custom value type.
Common situations: Metadata injection where the injected field's type was changed to an unhandled type (e.g. TYPE_BINARY) in a transformation step; custom ValueMeta plugins that add new types not supported by RowMetaAndData.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unknown column
- Unknown conversion from
- Wrong value conversion to
- Cannot assemble shared object of type
- get zero function undefined for data type: <type.getType()>
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/9609743f7640798c.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/RowMetaAndData.java:312
case ValueMetaInterface.TYPE_STRING:
return rowMeta.getString( data, idx ) == null;
case ValueMetaInterface.TYPE_BOOLEAN:
return rowMeta.getBoolean( data, idx ) == null;
case ValueMetaInterface.TYPE_INTEGER:
return rowMeta.getInteger( data, idx ) == null;
case ValueMetaInterface.TYPE_NUMBER:
return rowMeta.getNumber( data, idx ) == null;
case ValueMetaInterface.TYPE_BIGNUMBER:
return rowMeta.getBigNumber( data, idx ) == null;
case ValueMetaInterface.TYPE_BINARY:
return rowMeta.getBinary( data, idx ) == null;
case ValueMetaInterface.TYPE_DATE:
case ValueMetaInterface.TYPE_TIMESTAMP:
return rowMeta.getDate( data, idx ) == null;
case ValueMetaInterface.TYPE_INET:
return rowMeta.getString( data, idx ) == null;
}
throw new KettleValueException( "Unknown source type: " + metaType.getTypeDesc() );
}
/**
* Converts string value into specified type. Used for constant injection.
*/
public static Object getStringAsJavaType( String vs, Class<?> destinationType, InjectionTypeConverter converter )
throws KettleValueException {
if ( String.class.isAssignableFrom( destinationType ) ) {
return converter.string2string( vs );
} else if ( int.class.isAssignableFrom( destinationType ) ) {
return converter.string2intPrimitive( vs );
} else if ( Integer.class.isAssignableFrom( destinationType ) ) {
return converter.string2integer( vs );
} else if ( long.class.isAssignableFrom( destinationType ) ) {
return converter.string2longPrimitive( vs );
} else if ( Long.class.isAssignableFrom( destinationType ) ) {
return converter.string2long( vs );
} else if ( boolean.class.isAssignableFrom( destinationType ) ) {View on GitHub (pinned to f3058517a1)