pentaho/pentaho-kettle · error · KettleValueException

: Unknown storage type " + storageType + " specified.

Error message

 : Unknown storage type " + storageType + " specified.

What it means

Inside ValueMetaTimestamp.getTimestamp(), when the field's declared data type is TYPE_STRING the code switches on storageType (NORMAL, BINARY_STRING, INDEXED). If storageType holds any other value, the default branch throws this KettleValueException. It signals a corrupted/unknown storage-type constant on the value metadata rather than a data conversion failure.

Solutions

  1. Check the value meta's storage type before the call: System.out.println(valueMeta.getStorageType()) and set it explicitly with valueMeta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL ).
  2. If the metadata came from a serialized transformation, re-open and re-save it with the current PDI version to normalize storage type codes.
  3. Call valueMeta.setStorageType(STORAGE_TYPE_NORMAL) after construction if you built the ValueMeta manually and never assigned a storage type.
  4. Verify you are not accidentally passing a different ValueMetaInterface implementation whose storage-type constants diverge from the ones this switch expects.

Example fix

// before
ValueMetaInterface meta = new ValueMeta( "ts", ValueMetaInterface.TYPE_STRING ); // storageType defaults to 0
Timestamp t = meta.getTimestamp( object ); // throws Unknown storage type
// after
ValueMetaInterface meta = new ValueMeta( "ts", ValueMetaInterface.TYPE_STRING );
meta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL );
Timestamp t = meta.getTimestamp( object );
Defensive patterns

Strategy: validation

Validate before calling

int st = meta.getStorageType();
if ( st != ValueMetaInterface.STORAGE_TYPE_NORMAL
  && st != ValueMetaInterface.STORAGE_TYPE_BINARY_STRING
  && st != ValueMetaInterface.STORAGE_TYPE_INDEXED ) {
  meta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL );
}

Type guard

boolean hasKnownStorageType( ValueMetaInterface meta ) {
  int st = meta.getStorageType();
  return st == ValueMetaInterface.STORAGE_TYPE_NORMAL
    || st == ValueMetaInterface.STORAGE_TYPE_BINARY_STRING
    || st == ValueMetaInterface.STORAGE_TYPE_INDEXED;
}

Try / catch

try {
  t = meta.getTimestamp( value );
} catch ( KettleValueException e ) {
  if ( e.getMessage().contains( "Unknown storage type" ) ) {
    meta.setStorageType( ValueMetaInterface.STORAGE_TYPE_NORMAL );
    t = meta.getTimestamp( value );
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling getTimestamp(object) on a ValueMetaTimestamp whose type is TYPE_STRING and whose storageType field has been set to an unrecognized value (negative, 0 when undefined, or any constant outside STORAGE_TYPE_NORMAL/BINARY_STRING/INDEXED).

Common situations: Metadata deserialized from an old or newer KTR/KJB version where storage type codes differ; manually constructing ValueMeta and setting storage type via setStorageType with a wrong literal; uninitialized storageType (0) combined with TYPE_STRING data.

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


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/587530d545003ba3. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaTimestamp.java:139

  public String getString( Object object ) throws KettleValueException {
    return convertTimestampToString( getTimestamp( object ) );
  }

  public Timestamp getTimestamp( Object object ) throws KettleValueException {
    if ( object == null ) {
      return null;
    }
    switch ( type ) {
      case TYPE_TIMESTAMP:
        switch ( storageType ) {
          case STORAGE_TYPE_NORMAL:
            return (Timestamp) object;
          case STORAGE_TYPE_BINARY_STRING:
            return (Timestamp) convertBinaryStringToNativeType( (byte[]) object );
          case STORAGE_TYPE_INDEXED:
            return (Timestamp) index[ ( (Integer) object ).intValue() ];
          default:
            throw new KettleValueException( toString() + " : Unknown storage type " + storageType + " specified." );
        }
      case TYPE_STRING:
        switch ( storageType ) {
          case STORAGE_TYPE_NORMAL:
            return convertStringToTimestamp( (String) object );
          case STORAGE_TYPE_BINARY_STRING:
            return convertStringToTimestamp( (String) convertBinaryStringToNativeType( (byte[]) object ) );
          case STORAGE_TYPE_INDEXED:
            return convertStringToTimestamp( (String) index[ ( (Integer) object ).intValue() ] );
          default:
            throw new KettleValueException( toString() + " : Unknown storage type " + storageType + " specified." );
        }
      case TYPE_NUMBER:
        switch ( storageType ) {
          case STORAGE_TYPE_NORMAL:
            return convertNumberToTimestamp( (Double) object );
          case STORAGE_TYPE_BINARY_STRING:
            return convertNumberToTimestamp( (Double) convertBinaryStringToNativeType( (byte[]) object ) );

View on GitHub (pinned to f3058517a1)