pentaho/pentaho-kettle · error · KettleValueException

Janino.Error.ValueTypeMismatch

Janino.Error.ValueTypeMismatch

Error message

Janino.Error.ValueTypeMismatch

What it means

Thrown by the Janino step's calcFields when a formula's result type does not match the declared (or replaced field's) value type and no automatic Integer->Long conversion applies. Kettle enforces that the Java result class is assignable to the configured ValueMeta type.

Solutions

  1. Set the formula's 'Value type' to match what the expression returns (e.g. String, BigNumber).
  2. Cast or convert inside the formula to the expected type (e.g. Long.parseLong(...), new BigDecimal(...)).
  3. If replacing a field, ensure the output type matches the replaced field's type or use a Select Values type conversion after the step.
  4. Log the formula result class (see the exception text) to confirm the actual Java type.

Example fix

// before (value type: Integer)
return price * qty; // yields BigDecimal
// after
return (long) (price.doubleValue() * qty);
Defensive patterns

Strategy: try-catch

Validate before calling

// Check declared value type vs. expected Java type
ValueMetaInterface vm = ValueMetaFactory.createValueMeta(fn.getValueType());
// e.g. TYPE_STRING expects String results; TYPE_NUMBER expects Double

Type guard

boolean isCompatible(ValueMetaInterface vm, Object result) {
  if (result == null) return true;
  if (vm.getNativeDataTypeClass().isAssignableFrom(result.getClass())) return true;
  return result instanceof Integer && vm.getType() == ValueMetaInterface.TYPE_INTEGER;
}

Try / catch

try { row = calcFields(row); } catch (KettleValueException e) { logError("Formula type mismatch: " + e.getMessage()); throw e; }

Prevention

When it happens

Trigger: getNativeDataTypeClass().isAssignableFrom(result.getClass()) is false and the result is not an Integer for TYPE_INTEGER — e.g. formula returns String/BigDecimal/Double while the field value type is Integer, Number, Date, or Boolean.

Common situations: Changing a formula but leaving the old 'Value type' in the dialog; replacing a field whose type differs from the formula output; Janino returning boxed types like BigDecimal from arithmetic.

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/3c10358797733bfa. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/janino/Janino.java:196

        for ( int x = 0; x < argumentIndexes.size(); x++ ) {
          int index = argumentIndexes.get( x );
          ValueMetaInterface outputValueMeta = data.outputRowMeta.getValueMeta( index );
          argumentData[x] = outputValueMeta.convertToNormalStorageType( outputRowData[index] );
        }

        Object formulaResult = data.expressionEvaluators[i].evaluate( argumentData );

        Object value = null;
        if ( formulaResult == null ) {
          value = null;
        } else {
          ValueMetaInterface valueMeta = data.returnType[i];
          if ( valueMeta.getNativeDataTypeClass().isAssignableFrom( formulaResult.getClass() ) ) {
            value = formulaResult;
          } else if ( formulaResult instanceof Integer && valueMeta.getType() == ValueMetaInterface.TYPE_INTEGER ) {
            value = ( (Integer) formulaResult ).longValue();
          } else {
            throw new KettleValueException(
              BaseMessages.getString( PKG, "Janino.Error.ValueTypeMismatch", valueMeta.getTypeDesc(),
                meta.getFormula()[i].getFieldName(), formulaResult.getClass(), meta.getFormula()[i].getFormula() ) );
          }
        }

        // We're done, store it in the row with all the data, including the temporary data...
        //
        if ( data.replaceIndex[i] < 0 ) {
          outputRowData[tempIndex++] = value;
        } else {
          outputRowData[data.replaceIndex[i]] = value;
        }
      }

      return outputRowData;
    } catch ( Exception e ) {
      throw new KettleValueException( e );
    }

View on GitHub (pinned to f3058517a1)