{"record":{"id":"2eef5e35d0983edd","repo":"pentaho/pentaho-kettle","slug":"api-coding-error-please-specify-the-conversion-metadata","errorCode":null,"errorMessage":"API coding error: please specify the conversion metadata before attempting to convert value ","messagePattern":"API coding error: please specify the conversion metadata before attempting to convert value ","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java","lineNumber":3935,"sourceCode":"      default:\n        throw new KettleValueException( toString() + \" : I can't convert the specified value to data type : \"\n            + getType() );\n    }\n  }\n\n  /**\n   * Convert an object to the data type specified in the conversion metadata\n   *\n   * @param data\n   *          The data\n   * @return The data converted to the storage data type\n   * @throws KettleValueException\n   *           in case there is a conversion error.\n   */\n  @Override\n  public Object convertDataUsingConversionMetaData( Object data ) throws KettleValueException {\n    if ( conversionMetadata == null ) {\n      throw new KettleValueException(\n          \"API coding error: please specify the conversion metadata before attempting to convert value \" + name );\n    }\n\n    // Suppose we have an Integer 123, length 5\n    // The string variation of this is \" 00123\"\n    // To convert this back to an Integer we use the storage metadata\n    // Specifically, in method convertStringToInteger() we consult the\n    // storageMetaData to get the correct conversion mask\n    // That way we're always sure that a conversion works both ways.\n    //\n\n    switch ( conversionMetadata.getType() ) {\n      case TYPE_STRING:\n        return getString( data );\n      case TYPE_INTEGER:\n        return getInteger( data );\n      case TYPE_NUMBER:\n        return getNumber( data );","sourceCodeStart":3917,"sourceCodeEnd":3953,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java#L3917-L3953","documentation":"ValueMetaBase.convertDataUsingConversionMetaData(Object) requires the field's conversionMetadata (set via setConversionMetadata) to know which type/mask to convert to. When it is null, the API throws this KettleValueException stating it is an API coding error — the caller must configure conversion metadata before invoking the conversion. Lazy-conversion/storage metadata round-trips depend on this setup.","triggerScenarios":"Calling convertDataUsingConversionMetaData(data) on a ValueMetaBase where setConversionMetadata(ValueMetaInterface) was never called — common with lazily converted binary-string fields being converted to their native type during row serialization/deserialization.","commonSituations":"Custom steps or plugin code that clones ValueMeta objects but forgets to copy conversionMetadata; constructing ValueMeta programmatically for lazy conversion without storage/conversion metadata; XML round-trips where conversion metadata section was dropped; wrong method used where convertToNormalStorageType() was intended.","solutions":["Call valueMeta.setConversionMetadata(storageMeta) with a properly typed metadata object before converting.","When copying/cloning value metas, ensure conversionMetadata is carried over (clone() normally does; manual copies often do not).","If you only need normal/native data and no format masks, use convertToNormalStorageType(data) instead.","Check that XML save/load includes the conversion metadata so deserialized fields retain it."],"exampleFix":"// before\nValueMetaInterface meta = new ValueMeta(\"amount\", ValueMetaInterface.TYPE_INTEGER);\nmeta.setStorageType(ValueMetaInterface.STORAGE_TYPE_BINARY_STRING);\nObject v = meta.convertDataUsingConversionMetaData(data); // throws\n\n// after\nValueMetaInterface storageMeta = new ValueMeta(\"amount\", ValueMetaInterface.TYPE_STRING);\nstorageMeta.setConversionMask(\"000000;\");\nmeta.setConversionMetadata(storageMeta);\nObject v = meta.convertDataUsingConversionMetaData(data);","handlingStrategy":"validation","validationCode":"if (meta.getConversionMetadata() == null) {\n  throw new IllegalStateException(\"Value \" + meta.getName()\n      + \" needs setConversionMetadata() before convertDataUsingConversionMetaData\");\n}","typeGuard":"boolean conversionReady(ValueMetaInterface m) {\n  return m.getConversionMetadata() != null;\n}","tryCatchPattern":"try { Object v = meta.convertDataUsingConversionMetaData(data); } catch (KettleValueException e) {\n  if (e.getMessage().contains(\"API coding error\")) {\n    logger.logError(\"Conversion metadata missing on field \" + meta.getName()\n        + \"; check clone/copy of value meta\");\n  }\n  throw e;\n}","preventionTips":["Call setConversionMetadata() right after enabling binary-string/lazy storage.","Use clone() instead of manual field-by-field copies so conversionMetadata survives.","Confirm XML serialization retains the conversion metadata section.","Use convertToNormalStorageType() when format-mask round-tripping is not needed."],"tags":["pdi","kettle","conversion-metadata","api-misuse"],"backgroundTag":"missing-required-config-field","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"}