{"record":{"id":"995d371ace8d5832","repo":"pentaho/pentaho-kettle","slug":"unknown-storage-type-valuemetabase","errorCode":null,"errorMessage":" : Unknown storage type : ","messagePattern":" : Unknown storage type : ","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java","lineNumber":3830,"sourceCode":"              // BACKLOG-18754 - if there is a storage conversion mask, we should use\n              // it as the mask for meta2 (meta2 can have specific storage type and type, so\n              // it can't be used directly to convert data2 to binary string)\n              ValueMetaInterface meta2StorageMask = meta2.clone();\n              meta2StorageMask.setConversionMask( storageMetadata.getConversionMask() );\n              return compare( data1, meta2StorageMask.convertToBinaryStringStorageType( data2 ) );\n            } else {\n              return compare( data1, meta2.convertToBinaryStringStorageType( data2 ) );\n            }\n          case STORAGE_TYPE_INDEXED:\n            switch ( meta2.getStorageType() ) {\n              case STORAGE_TYPE_INDEXED:\n                return compare( data1, data2 ); // not accessible, just to make sure.\n              case STORAGE_TYPE_NORMAL:\n                return -meta2.compare( data2, convertToNormalStorageType( data1 ) );\n              case STORAGE_TYPE_BINARY_STRING:\n                return -meta2.compare( data2, convertToBinaryStringStorageType( data1 ) );\n              default:\n                throw new KettleValueException( meta2.toStringMeta() + \" : Unknown storage type : \"\n                    + meta2.getStorageType() );\n\n            }\n          default:\n            throw new KettleValueException( toStringMeta() + \" : Unknown storage type : \" + getStorageType() );\n        }\n      } else if ( ValueMetaInterface.TYPE_INTEGER == getType() && ValueMetaInterface.TYPE_NUMBER == meta2.getType() ) {\n        // BACKLOG-18738\n        // compare Double to Integer\n        return -meta2.compare( data2, meta2.convertData( this, data1 ) );\n      }\n\n      // If the data types are not the same, the first one is the driver...\n      // The second data type is converted to the first one.\n      //\n      return compare( data1, convertData( meta2, data2 ) );\n    } catch ( Exception e ) {\n      throw new KettleValueException(","sourceCodeStart":3812,"sourceCodeEnd":3848,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java#L3812-L3848","documentation":"Inside ValueMetaBase.compare(data1, meta2, data2), when this value has STORAGE_TYPE_INDEXED, it delegates to a nested switch on meta2's storage type; an unrecognized meta2 storage type throws this KettleValueException naming meta2. It signals invalid storage metadata on the right-hand value during cross-storage-type comparison.","triggerScenarios":"Comparing values where this meta's storageType is STORAGE_TYPE_INDEXED and meta2.getStorageType() is not NORMAL, BINARY_STRING, or INDEXED (i.e. an out-of-range/corrupt integer, typically > 2 or negative).","commonSituations":"Metadata deserialized from hand-edited or foreign-version XML; programmatic setStorageType() with a wrong constant; indexed values (e.g. from VALUEMAP step) compared against rows built by custom plugins with bogus storage metadata.","solutions":["Fix meta2's storage type to one of STORAGE_TYPE_NORMAL/BINARY_STRING/INDEXED before comparing.","Verify where meta2 metadata originates (which step or XML) and re-generate it with valid constants.","Add a guard comparing meta2.getStorageType() against the valid range (0..2) before calling compare().","If data comes from an older/newer PDI file, re-save it with the runtime version so storage metadata is normalized."],"exampleFix":"// before\nint cmp = meta1.compare(data1, meta2, data2); // meta2 storageType invalid\n\n// after\nint st = meta2.getStorageType();\nif (st < ValueMetaInterface.STORAGE_TYPE_NORMAL || st > ValueMetaInterface.STORAGE_TYPE_INDEXED) {\n  meta2.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);\n}\nint cmp = meta1.compare(data1, meta2, data2);","handlingStrategy":"validation","validationCode":"int st = meta2.getStorageType();\nif (st < ValueMetaInterface.STORAGE_TYPE_NORMAL || st > ValueMetaInterface.STORAGE_TYPE_INDEXED) {\n  throw new KettleValueException(\"meta2 has invalid storage type \" + st);\n}\nint cmp = meta1.compare(data1, meta2, data2);","typeGuard":"boolean isValidStorageType(ValueMetaInterface m) {\n  int st = m.getStorageType();\n  return st >= ValueMetaInterface.STORAGE_TYPE_NORMAL && st <= ValueMetaInterface.STORAGE_TYPE_INDEXED;\n}","tryCatchPattern":"try { cmp = meta1.compare(data1, meta2, data2); } catch (KettleValueException e) {\n  if (e.getMessage().contains(\"Unknown storage type\")) {\n    meta2.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);\n    cmp = meta1.compare(data1, meta2, data2);\n  } else throw e;\n}","preventionTips":["Validate storage type range when ingesting metadata from external sources.","Use only the interface constants, never raw integers, for setStorageType().","Fix metadata producers (custom steps) that emit unnormalized storage values."],"tags":["pdi","kettle","storage-type","comparison"],"backgroundTag":"invalid-enum-value","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"}