pentaho/pentaho-kettle · error · KettleValueException
<toString()>: unable to make copy of value type: <getType()>
Error message
<toString()>: unable to make copy of value type: <getType()>
What it means
Thrown by ValueMetaBase.getValue (copy-value path) when the value's data type (getType()) has no case in the copy switch — i.e. Kettle doesn't know how to clone a value of that type. Only TYPE_SERIALIZABLE deliberately bypasses copying; any other unrecognized/non-primitive type hits the default branch.
Solutions
- Log/print getType() and getName() on the offending ValueMeta and map the field to a standard type (String/Number/Date/Binary/BigDecimal/Boolean/Integer/Timestamp).
- Implement Cloneable/Serializable properly or rely on the TYPE_SERIALIZABLE exemption if the value is a custom object (cloneable).
- Align plugin and PDI versions so all type codes in flight are understood by the running core.
- Strip or convert custom-typed fields (Select Values → remove/meta-change) before steps that clone rows.
Example fix
// before: custom type code 99 clones fine nowhere vm.setType(99); rowMeta.cloneRow(row); // -> "unable to make copy of value type: 99" // after vm.setType(ValueMetaInterface.TYPE_STRING); // or mark as serializable // ValueMetaInterface.TYPE_SERIALIZABLE values are returned as-is without copying
Defensive patterns
Strategy: type-guard
Validate before calling
int t = valueMeta.getType();
if (t != ValueMetaInterface.TYPE_STRING && t != ValueMetaInterface.TYPE_NUMBER
&& t != ValueMetaInterface.TYPE_INTEGER && t != ValueMetaInterface.TYPE_DATE
&& t != ValueMetaInterface.TYPE_BOOLEAN && t != ValueMetaInterface.TYPE_BIGNUMBER
&& t != ValueMetaInterface.TYPE_BINARY && t != ValueMetaInterface.TYPE_TIMESTAMP
&& t != ValueMetaInterface.TYPE_SERIALIZABLE) {
throw new IllegalStateException("Non-copyable value type: " + t);
} Type guard
static boolean isCloneableType(ValueMetaInterface vm) {
switch (vm.getType()) {
case ValueMetaInterface.TYPE_STRING:
case ValueMetaInterface.TYPE_NUMBER:
case ValueMetaInterface.TYPE_INTEGER:
case ValueMetaInterface.TYPE_DATE:
case ValueMetaInterface.TYPE_BOOLEAN:
case ValueMetaInterface.TYPE_BIGNUMBER:
case ValueMetaInterface.TYPE_BINARY:
case ValueMetaInterface.TYPE_TIMESTAMP:
case ValueMetaInterface.TYPE_SERIALIZABLE:
return true;
default:
return false;
}
} Try / catch
try {
Object copy = valueMeta.getValue(original);
} catch (KettleValueException e) {
throw new IllegalStateException("Field " + valueMeta.getName() + " has unclonable type " + valueMeta.getType(), e);
} Prevention
- Restrict row fields to standard TYPE_* constants; convert custom types upstream
- Keep plugins on versions compatible with the PDI core's type switch
- Mark custom object fields as TYPE_SERIALIZABLE (and make them Cloneable) so they bypass copying
When it happens
Trigger: getValue(Object) called during row duplication (RowMeta.cloneRow, step row copying) where getType() returns a type code outside the standard TYPE_* set — custom ValueMeta types, corrupted metadata, or a type added by a newer/older Kettle version than the running one.
Common situations: Mixing Kettle plugin versions where a plugin registers a new data type the core doesn't switch on; deserialized repository metadata with a bad 'value type' integer; passing Kettle rows containing plugin-specific ValueMeta through generic row-cloning code.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- TeraFast.Exception.TypeNotSupported
- API coding error: please specify the conversion metadata…
- Calculator.Error.NoNameField
- Calculator.Error.UnableFindField
- Calculator.ErrorInStepRunning
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/62459e1405c606c3.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:1700
// inexpensive too.
case ValueMetaInterface.TYPE_BINARY:
if ( object instanceof java.lang.String ) {
return object;
} else {
byte[] origin = (byte[]) object;
byte[] target = new byte[origin.length];
System.arraycopy( origin, 0, target, 0, origin.length );
return target;
}
case ValueMetaInterface.TYPE_SERIALIZABLE:
// Let's not create a copy but simply return the same value.
//
return object;
default:
throw new KettleValueException( toString() + ": unable to make copy of value type: " + getType() );
}
} else {
return object;
}
}
@Override
public String getCompatibleString( Object object ) throws KettleValueException {
try {
String string;
switch ( type ) {
case TYPE_DATE:
switch ( storageType ) {
case STORAGE_TYPE_NORMAL:
string = convertDateToCompatibleString( (Date) object );View on GitHub (pinned to f3058517a1)