pentaho/pentaho-kettle · error · KettleValueException

Unexpected conversion error while converting value [" +…

Error message

Unexpected conversion error while converting value [" + toString() + "] to a Number

What it means

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().

Solutions

  1. Read the chained cause (e.getCause()) to identify the real failure (ClassCastException vs NumberFormatException) and fix the value or metadata accordingly.
  2. 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).
  3. Pre-validate/pre-clean string data (trim, remove locale separators) before numeric conversion, or set the correct conversion mask/format on the value meta.
  4. Catch KettleValueException around getNumber() and route bad rows to an error handling stream instead of failing the transformation.

Example fix

// before
Double n = valueMeta.getNumber(row[i]); // wraps NumberFormatException

// after
try {
  Double n = valueMeta.getNumber(row[i]);
} catch (KettleValueException e) {
  logError("Conversion failed for " + valueMeta.getName() + ": " + e.getCause(), e);
  putError(...); // send to error handling
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!meta.isNull(value) && meta.getType() == ValueMetaInterface.TYPE_STRING) {
  String s = meta.getString(value).trim();
  if (!s.isEmpty() && !s.matches("[-+]?[0-9.,Ee]+")) {
    throw new IllegalArgumentException("Non-numeric value for " + meta.getName() + ": " + s);
  }
}

Type guard

boolean isSafelyConvertibleToNumber(ValueMetaInterface m, Object v) {
  try { return v == null || m.isNull(v) || m.getNumber(v) != null; }
  catch (KettleValueException e) { return false; }
}

Try / catch

try {
  Double n = meta.getNumber(value);
} catch (KettleValueException e) {
  Throwable cause = e.getCause();
  log.error("Number conversion failed for " + meta.getName() + ": " + (cause != null ? cause.toString() : e.getMessage()));
  // route row to error handling
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

          switch ( storageType ) {
            case STORAGE_TYPE_NORMAL:
              return convertBooleanToNumber( (Boolean) object );
            case STORAGE_TYPE_BINARY_STRING:
              return convertBooleanToNumber( (Boolean) convertBinaryStringToNativeType( (byte[]) object ) );
            case STORAGE_TYPE_INDEXED:
              return convertBooleanToNumber( (Boolean) index[( (Integer) object ).intValue()] );
            default:
              throw new KettleValueException( toString() + " : Unknown storage type " + storageType + " specified." );
          }
        case TYPE_BINARY:
          throw new KettleValueException( toString() + " : I don't know how to convert binary values to numbers." );
        case TYPE_SERIALIZABLE:
          throw new KettleValueException( toString() + " : I don't know how to convert serializable values to numbers." );
        default:
          throw new KettleValueException( toString() + " : Unknown type " + type + " specified." );
      }
    } catch ( Exception e ) {
      throw new KettleValueException( "Unexpected conversion error while converting value [" + toString()
          + "] to a Number", e );
    }
  }

  @Override
  public Long getInteger( Object object ) throws KettleValueException {
    try {
      if ( isNull( object ) ) {
        return null;
      }
      switch ( type ) {
        case TYPE_INTEGER:
          switch ( storageType ) {
            case STORAGE_TYPE_NORMAL:
              return (Long) object;
            case STORAGE_TYPE_BINARY_STRING:
              return (Long) convertBinaryStringToNativeType( (byte[]) object );
            case STORAGE_TYPE_INDEXED:

View on GitHub (pinned to f3058517a1)