pentaho/pentaho-kettle · error · KettleValueException

The value: [ ] is a negative number. The 'sqrt' function…

Error message

The value: [${num}] is a negative number. The 'sqrt' function only works with non-negative numbers.

What it means

ValueDataUtil.sqrt() computes the square root of a numeric field (Number, Integer, or BigNumber). When the input value is negative, Math.sqrt would yield NaN, so Kettle throws KettleValueException instead of returning a silently wrong result. The exception message embeds the offending value so the failing row/data can be identified.

Solutions

  1. Check the input data: find rows feeding the SQRT calculation where the value is negative and fix them at the source
  2. Guard the expression: compute SQRT only when value >= 0, e.g. use an IF/ternary in the Calculator or Formula step: value < 0 ? null : SQRT(value)
  3. Take ABS() first if sign is irrelevant: SQRT(ABS(value))
  4. Apply the square root to a squared quantity (variance/stddev pattern) so the operand is always non-negative

Example fix

// before (Calculator/UDF via ValueDataUtil)
Object r = ValueDataUtil.sqrt(metaA, dataA); // throws if dataA < 0
// after
Object r = (metaA.getNumber(dataA) >= 0)
    ? ValueDataUtil.sqrt(metaA, dataA)
    : null;
Defensive patterns

Strategy: validation

Validate before calling

if (metaA != null && metaA.getType() == ValueMetaInterface.TYPE_NUMBER && metaA.getNumber(dataA) != null && metaA.getNumber(dataA) >= 0) { result = ValueDataUtil.sqrt(metaA, dataA); } else { result = null; /* or log & skip row */ }

Type guard

boolean isNonNegativeNumeric(ValueMetaInterface meta, Object data) {
  if (meta == null || data == null) return false;
  int t = meta.getType();
  if (t != ValueMetaInterface.TYPE_NUMBER && t != ValueMetaInterface.TYPE_INTEGER && t != ValueMetaInterface.TYPE_BIGNUMBER) return false;
  Number n = (Number) meta.convertData(data);
  return n.doubleValue() >= 0;
}

Try / catch

try {
  result = ValueDataUtil.sqrt(metaA, dataA);
} catch (KettleValueException e) {
  logError("SQRT of negative value in row " + getRowNr() + ": " + e.getMessage());
  putRow(outputRowMeta, RowDataUtil.addValueData(inputRow, outputRowMeta.size(), null)); // null result, keep pipeline flowing
}

Prevention

When it happens

Trigger: Calling ValueDataUtil.sqrt(metaA, dataA) (or a Calculator step / formula using the SQRT function) where metaA.getType() is TYPE_NUMBER and dataA is a negative double (num < 0).

Common situations: Calculator step computing sqrt of a difference that can go negative (e.g. variance from mismatched column order), formula fields over raw measurements that can be negative, importing negative sensor values, sign errors in upstream transformations.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/ValueDataUtil.java:931

      }
    }
    return MathContext.UNLIMITED;
  }

  public static Object sqrt( ValueMetaInterface metaA, Object dataA ) throws KettleValueException {
    if ( dataA == null ) {
      return null;
    }

    Double num;

    switch ( metaA.getType() ) {
      case ValueMetaInterface.TYPE_NUMBER:
        num = metaA.getNumber( dataA );
        if ( num >= 0 ) {
          return new Double( Math.sqrt( num.doubleValue() ) );
        }
        throw new KettleValueException( valueNotNegative( num ) );
      case ValueMetaInterface.TYPE_INTEGER:
        num = metaA.getNumber( dataA );
        if ( num >= 0 ) {
          return new Long( Math.round( Math.sqrt( num.doubleValue() ) ) );
        }
        throw new KettleValueException( valueNotNegative( num ) );
      case ValueMetaInterface.TYPE_BIGNUMBER:
        num = metaA.getNumber( dataA );
        if ( num >= 0 ) {
          return BigDecimal.valueOf( Math.sqrt( num.doubleValue() ) );
        }
        throw new KettleValueException( valueNotNegative( num ) );

      default:
        throw new KettleValueException( "The 'sqrt' function only works on numeric data." );
    }
  }

View on GitHub (pinned to f3058517a1)