pentaho/pentaho-kettle · error · KettleValueException

<toString()> : Unknown storage type

Error message

<toString()> : Unknown storage type <storageType> specified.

What it means

ValueMetaBase converts a Kettle value to its string form based on the value's storageType. When the storage type is not one of the known constants (STORAGE_TYPE_NORMAL, STORAGE_TYPE_INDEXED, STORAGE_TYPE_BINARY_STRING), the switch falls through to its default arm and throws KettleValueException. This is a metadata-corruption / invalid-value-meta-state error: the ValueDataInterface object and the metadata disagree on how the raw data is stored.

Solutions

  1. Verify the ValueMeta's storageType with valueMeta.getStorageType() and set it to a valid constant: ValueMetaInterface.STORAGE_TYPE_NORMAL, STORAGE_TYPE_INDEXED, or STORAGE_TYPE_BINARY_STRING
  2. If you only need string output, call valueMeta.getStorageType() and normalize invalid values to STORAGE_TYPE_NORMAL before conversion
  3. Re-serialize/rebuild the transformation or step metadata that produced the invalid ValueMeta instead of hand-editing stored metadata
  4. Upgrade/align the Pentaho Kettle (PDI) version used to write and read the transformation to avoid metadata incompatibilities

Example fix

// before
ValueMetaBase meta = new ValueMetaBase("d", ValueMetaInterface.TYPE_DATE);
meta.setStorageType(42); // invalid
String s = meta.toString(data); // throws
// after
meta.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);
String s = meta.toString(data);
Defensive patterns

Strategy: validation

Validate before calling

private static boolean hasValidStorageType(ValueMetaInterface m) {
  int st = m.getStorageType();
  return st == ValueMetaInterface.STORAGE_TYPE_NORMAL
      || st == ValueMetaInterface.STORAGE_TYPE_INDEXED
      || st == ValueMetaInterface.STORAGE_TYPE_BINARY_STRING;
}
// call before conversion: if (!hasValidStorageType(meta)) meta.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);

Type guard

boolean isValidStorageType(ValueMetaInterface m) {
  switch (m.getStorageType()) {
    case ValueMetaInterface.STORAGE_TYPE_NORMAL:
    case ValueMetaInterface.STORAGE_TYPE_INDEXED:
    case ValueMetaInterface.STORAGE_TYPE_BINARY_STRING:
      return true;
    default:
      return false;
  }
}

Try / catch

try {
  String s = meta.toString(data);
} catch (KettleValueException e) {
  logError("Invalid storage type on field " + meta.getName() + ": " + e.getMessage());
  meta.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);
  String s = meta.toString(data); // retry with corrected metadata
}

Prevention

When it happens

Trigger: Calling toString()/getString() on a ValueMeta whose storageType field was set to an unrecognized integer (anything other than 0=NORMAL, 1=INDEXED, 2=BINARY_STRING) while the field's data type is TYPE_DATE; typically after hand-built ValueMeta objects, bad setStorageType() arguments, or corrupted serialized transformation metadata.

Common situations: Custom plugin code constructing ValueMetaBase directly with a wrong storage type constant; legacy transformations saved by old Pentaho versions whose metadata round-trips into an invalid storage type; index-based storage (STORAGE_TYPE_INDEXED) metadata combined with a data type whose switch arm doesn't cover the actual value.

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/8ad184ab94008e9c. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:1731

      switch ( type ) {
        case TYPE_DATE:
          switch ( storageType ) {
            case STORAGE_TYPE_NORMAL:
              string = convertDateToCompatibleString( (Date) object );
              break;
            case STORAGE_TYPE_BINARY_STRING:
              string = convertDateToCompatibleString( (Date) convertBinaryStringToNativeType( (byte[]) object ) );
              break;
            case STORAGE_TYPE_INDEXED:
              if ( object == null ) {
                string = null;
              } else {
                string = convertDateToCompatibleString( (Date) index[( (Integer) object ).intValue()] );
              }
              break;
            default:
              throw new KettleValueException( toString() + " : Unknown storage type " + storageType + " specified." );
          }
          break;

        case TYPE_NUMBER:
          switch ( storageType ) {
            case STORAGE_TYPE_NORMAL:
              string = convertNumberToCompatibleString( (Double) object );
              break;
            case STORAGE_TYPE_BINARY_STRING:
              string = convertNumberToCompatibleString( (Double) convertBinaryStringToNativeType( (byte[]) object ) );
              break;
            case STORAGE_TYPE_INDEXED:
              string =
                  object == null ? null : convertNumberToCompatibleString( (Double) index[( (Integer) object )
                      .intValue()] );
              break;
            default:
              throw new KettleValueException( toString() + " : Unknown storage type " + storageType + " specified." );

View on GitHub (pinned to f3058517a1)