{"record":{"id":"67846c9519b3733b","repo":"pentaho/pentaho-kettle","slug":"unexpected-conversion-error-while-converting-value-tostring","errorCode":null,"errorMessage":"Unexpected conversion error while converting value [\" + toString() + \"] to a Number","messagePattern":"Unexpected conversion error while converting value \\[\" \\+ toString\\(\\) \\+ \"\\] to a Number","errorType":"exception","errorClass":"KettleValueException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java","lineNumber":2048,"sourceCode":"          switch ( storageType ) {\n            case STORAGE_TYPE_NORMAL:\n              return convertBooleanToNumber( (Boolean) object );\n            case STORAGE_TYPE_BINARY_STRING:\n              return convertBooleanToNumber( (Boolean) convertBinaryStringToNativeType( (byte[]) object ) );\n            case STORAGE_TYPE_INDEXED:\n              return convertBooleanToNumber( (Boolean) index[( (Integer) object ).intValue()] );\n            default:\n              throw new KettleValueException( toString() + \" : Unknown storage type \" + storageType + \" specified.\" );\n          }\n        case TYPE_BINARY:\n          throw new KettleValueException( toString() + \" : I don't know how to convert binary values to numbers.\" );\n        case TYPE_SERIALIZABLE:\n          throw new KettleValueException( toString() + \" : I don't know how to convert serializable values to numbers.\" );\n        default:\n          throw new KettleValueException( toString() + \" : Unknown type \" + type + \" specified.\" );\n      }\n    } catch ( Exception e ) {\n      throw new KettleValueException( \"Unexpected conversion error while converting value [\" + toString()\n          + \"] to a Number\", e );\n    }\n  }\n\n  @Override\n  public Long getInteger( Object object ) throws KettleValueException {\n    try {\n      if ( isNull( object ) ) {\n        return null;\n      }\n      switch ( type ) {\n        case TYPE_INTEGER:\n          switch ( storageType ) {\n            case STORAGE_TYPE_NORMAL:\n              return (Long) object;\n            case STORAGE_TYPE_BINARY_STRING:\n              return (Long) convertBinaryStringToNativeType( (byte[]) object );\n            case STORAGE_TYPE_INDEXED:","sourceCodeStart":2030,"sourceCodeEnd":2066,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java#L2030-L2066","documentation":"This is the catch-all rethrow at the end of ValueMetaBase.getNumber(): any unexpected Exception thrown while converting the stored value to a Double (e.g. ClassCastException from a wrongly stored object, NumberFormatException deep inside convertStringToNumber, NullPointerException on a bad index lookup) is wrapped in a KettleValueException with this 'Unexpected conversion error ... to a Number' message. The original cause is attached, so inspect getCause().","triggerScenarios":"Calling ValueMeta.getNumber(Object) when the underlying object does not match the declared storage type (e.g. metadata says TYPE_INTEGER/STORAGE_TYPE_NORMAL but the value is a String), or a numeric string fails parsing during conversion.","commonSituations":"Rows built manually with mismatched Java types vs value metadata; data from heterogeneous sources (CSV with non-numeric text in a Number column); clustered/serialized rows whose storage metadata drifted from actual values; custom steps that put wrong-typed objects into fields.","solutions":["Read the chained cause (e.getCause()) to identify the real failure (ClassCastException vs NumberFormatException) and fix the value or metadata accordingly.","Ensure each field's ValueMeta storage type matches the actual Java object stored (Long for STORAGE_TYPE_NORMAL INTEGER, Double for NUMBER, byte[] for BINARY_STRING, Integer+index array for INDEXED).","Pre-validate/pre-clean string data (trim, remove locale separators) before numeric conversion, or set the correct conversion mask/format on the value meta.","Catch KettleValueException around getNumber() and route bad rows to an error handling stream instead of failing the transformation."],"exampleFix":"// before\nDouble n = valueMeta.getNumber(row[i]); // wraps NumberFormatException\n\n// after\ntry {\n  Double n = valueMeta.getNumber(row[i]);\n} catch (KettleValueException e) {\n  logError(\"Conversion failed for \" + valueMeta.getName() + \": \" + e.getCause(), e);\n  putError(...); // send to error handling\n}","handlingStrategy":"try-catch","validationCode":"if (!meta.isNull(value) && meta.getType() == ValueMetaInterface.TYPE_STRING) {\n  String s = meta.getString(value).trim();\n  if (!s.isEmpty() && !s.matches(\"[-+]?[0-9.,Ee]+\")) {\n    throw new IllegalArgumentException(\"Non-numeric value for \" + meta.getName() + \": \" + s);\n  }\n}","typeGuard":"boolean isSafelyConvertibleToNumber(ValueMetaInterface m, Object v) {\n  try { return v == null || m.isNull(v) || m.getNumber(v) != null; }\n  catch (KettleValueException e) { return false; }\n}","tryCatchPattern":"try {\n  Double n = meta.getNumber(value);\n} catch (KettleValueException e) {\n  Throwable cause = e.getCause();\n  log.error(\"Number conversion failed for \" + meta.getName() + \": \" + (cause != null ? cause.toString() : e.getMessage()));\n  // route row to error handling\n}","preventionTips":["Always inspect e.getCause() — the wrapper hides the real ClassCastException/NumberFormatException.","Keep the declared storage type in sync with the actual Java objects placed in rows.","Clean and trim string data and set correct conversion masks before numeric conversions.","Use Kettle row error handling (putError) instead of letting one bad row kill the transformation."],"tags":["kettle","type-conversion","wrapped-exception","value-metadata"],"backgroundTag":"type-mismatch","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"}