pentaho/pentaho-kettle · error · KettleValueException
The 'round_custom' arg C has incorrect value
Error message
The 'round_custom' arg C has incorrect value: ${valueC} What it means
The round_custom helper takes a third argument C specifying the rounding mode, validated to be between Const.ROUND_HALF_CEILING and BigDecimal.ROUND_HALF_EVEN inclusive. If C is null or outside that range, this KettleValueException is thrown with the offending value. This guards against arbitrary integers being used as Java rounding modes.
Solutions
- Set field C to a valid rounding mode constant: use 1 (ROUND_HALF_CEILING/default), 2 (ROUND_HALF_DOWN), 4 (ROUND_HALF_UP), 5 (HALF_EVEN), 6 (CEILING), or the documented PDI range values.
- Ensure the C field is non-null and typed Integer in the Calculator step.
- Use a Value Mapper or Case step to normalize arbitrary mode inputs to supported constants before the calculation.
Example fix
// before: round_custom(A, B, C) with C=9 // after: round_custom(A, B, C) with C=4 // BigDecimal.ROUND_HALF_UP, inside valid range
Defensive patterns
Strategy: validation
Validate before calling
Long valueC = metaC.getInteger(dataC);
int min = Const.ROUND_HALF_CEILING;
int max = BigDecimal.ROUND_HALF_EVEN;
if (valueC == null || valueC < min || valueC > max) {
throw new KettleValueException("rounding mode must be between " + min + " and " + max + ", got " + valueC);
} Type guard
public static boolean isValidRoundingMode(Long mode) {
return mode != null && mode >= Const.ROUND_HALF_CEILING && mode <= BigDecimal.ROUND_HALF_EVEN;
} Try / catch
try {
result = ValueDataUtil.roundCustom(metaA, dataA, metaB, dataB, metaC, dataC);
} catch (KettleValueException e) {
logError("Invalid rounding mode in arg C: " + e.getMessage());
result = ValueDataUtil.round(metaA, dataA, metaB, dataB); // fallback to default rounding
} Prevention
- Only pass documented PDI rounding constants (values within ROUND_HALF_CEILING..ROUND_HALF_EVEN), not arbitrary ints or java.math.RoundingMode ordinals.
- Ensure the mode field is populated for every row (default empty values with an 'If field is null' step).
- Use a Value Mapper to normalize free-text rounding names to supported constants.
When it happens
Trigger: Calling round_custom (Calculator 'Round custom') where field C converts to an Integer outside the valid rounding-mode constants (e.g. 5, -1, or an empty/null field), because valid modes here span only 1..7 (ROUND_HALF_CEILING..ROUND_HALF_EVEN).
Common situations: User enters a rounding mode number that is not one of the documented PDI rounding constants; field C is empty or contains a garbage value; passing java.math.RoundingMode ordinals that don't line up with the accepted legacy int constants.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- The 'round' function only works on numeric data
- API coding error: please specify the conversion metadata…
- Calculator.Error.NoNameField
- Calculator.Error.UnableFindField
- Calculator.ErrorInStepRunning
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/fc0bf70bc7058a14.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:1331
* @param metaB
* Metadata of decimal places
* @param dataB
* decimal places
* @param metaC
* Metadata of rounding mode
* @param dataC
* rounding mode, e.g. java.math.BigDecimal.ROUND_HALF_EVEN
* @return The rounded value
* @throws KettleValueException
*/
public static Object round( ValueMetaInterface metaA, Object dataA, ValueMetaInterface metaB, Object dataB,
ValueMetaInterface metaC, Object dataC ) throws KettleValueException {
if ( dataA == null || dataB == null || dataC == null ) {
return null;
}
Long valueC = metaC.getInteger( dataC );
if ( valueC == null || valueC < Const.ROUND_HALF_CEILING || valueC > BigDecimal.ROUND_HALF_EVEN ) {
throw new KettleValueException( "The 'round_custom' arg C has incorrect value: " + valueC );
}
int roundingMode = valueC.intValue();
return round( metaA, dataA, metaB, dataB, roundingMode );
}
public static Object ceil( ValueMetaInterface metaA, Object dataA ) throws KettleValueException {
if ( dataA == null ) {
return null;
}
switch ( metaA.getType() ) {
case ValueMetaInterface.TYPE_NUMBER:
return new Double( Math.ceil( metaA.getNumber( dataA ).doubleValue() ) );
case ValueMetaInterface.TYPE_INTEGER:
return metaA.getInteger( dataA );
case ValueMetaInterface.TYPE_BIGNUMBER:
return new BigDecimal( Math.ceil( metaA.getNumber( dataA ).doubleValue() ) );
default:View on GitHub (pinned to f3058517a1)