{"record":{"id":"62459e1405c606c3","repo":"pentaho/pentaho-kettle","slug":"tostring-unable-to-make-copy-of-value-type-gettype","errorCode":null,"errorMessage":"<toString()>: unable to make copy of value type: <getType()>","messagePattern":"<toString\\(\\)>: unable to make copy of value type: <getType\\(\\)>","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java","lineNumber":1700,"sourceCode":"          // inexpensive too.\n\n        case ValueMetaInterface.TYPE_BINARY:\n          if ( object instanceof java.lang.String ) {\n            return object;\n          } else {\n            byte[] origin = (byte[]) object;\n            byte[] target = new byte[origin.length];\n            System.arraycopy( origin, 0, target, 0, origin.length );\n            return target;\n          }\n\n        case ValueMetaInterface.TYPE_SERIALIZABLE:\n          // Let's not create a copy but simply return the same value.\n          //\n          return object;\n\n        default:\n          throw new KettleValueException( toString() + \": unable to make copy of value type: \" + getType() );\n      }\n    } else {\n\n      return object;\n\n    }\n  }\n\n  @Override\n  public String getCompatibleString( Object object ) throws KettleValueException {\n    try {\n      String string;\n\n      switch ( type ) {\n        case TYPE_DATE:\n          switch ( storageType ) {\n            case STORAGE_TYPE_NORMAL:\n              string = convertDateToCompatibleString( (Date) object );","sourceCodeStart":1682,"sourceCodeEnd":1718,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java#L1682-L1718","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: custom type code 99 clones fine nowhere\nvm.setType(99);\nrowMeta.cloneRow(row); // -> \"unable to make copy of value type: 99\"\n// after\nvm.setType(ValueMetaInterface.TYPE_STRING); // or mark as serializable\n// ValueMetaInterface.TYPE_SERIALIZABLE values are returned as-is without copying","handlingStrategy":"type-guard","validationCode":"int t = valueMeta.getType();\nif (t != ValueMetaInterface.TYPE_STRING && t != ValueMetaInterface.TYPE_NUMBER\n    && t != ValueMetaInterface.TYPE_INTEGER && t != ValueMetaInterface.TYPE_DATE\n    && t != ValueMetaInterface.TYPE_BOOLEAN && t != ValueMetaInterface.TYPE_BIGNUMBER\n    && t != ValueMetaInterface.TYPE_BINARY && t != ValueMetaInterface.TYPE_TIMESTAMP\n    && t != ValueMetaInterface.TYPE_SERIALIZABLE) {\n    throw new IllegalStateException(\"Non-copyable value type: \" + t);\n}","typeGuard":"static boolean isCloneableType(ValueMetaInterface vm) {\n    switch (vm.getType()) {\n        case ValueMetaInterface.TYPE_STRING:\n        case ValueMetaInterface.TYPE_NUMBER:\n        case ValueMetaInterface.TYPE_INTEGER:\n        case ValueMetaInterface.TYPE_DATE:\n        case ValueMetaInterface.TYPE_BOOLEAN:\n        case ValueMetaInterface.TYPE_BIGNUMBER:\n        case ValueMetaInterface.TYPE_BINARY:\n        case ValueMetaInterface.TYPE_TIMESTAMP:\n        case ValueMetaInterface.TYPE_SERIALIZABLE:\n            return true;\n        default:\n            return false;\n    }\n}","tryCatchPattern":"try {\n    Object copy = valueMeta.getValue(original);\n} catch (KettleValueException e) {\n    throw new IllegalStateException(\"Field \" + valueMeta.getName() + \" has unclonable type \" + valueMeta.getType(), e);\n}","preventionTips":["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"],"tags":["pdi","value-type","clone","kettle"],"backgroundTag":"unsupported-operation","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}