pentaho/pentaho-kettle · error · KettleStepException

Unable to convert a value to integer while calculating the…

Error message

Unable to convert a value to integer while calculating the partition number

What it means

BaseStep.putError/partitioning code computes the partition number for a row by calling Partitioner.getPartition(rowMeta, row), which must convert a partitioning field value to an integer. When the field value cannot be converted (KettleValueException wrapped in KettleException), BaseStep rethrows it as a KettleStepException with this message. It means the row's partitioning column holds data that is not a valid integer.

Solutions

  1. Point the partitioner at a field that is guaranteed Integer type (add a 'Select values' / 'Fields select' or Calculator step to convert it beforehand).
  2. If partitioning on strings, ensure the mapping field contains only numeric strings, or switch to a partitioner that handles the type.
  3. Clean/null-guard the data upstream: filter or default rows whose partition field is null or non-numeric.
  4. Catch KettleStepException in a calling routine and inspect the cause (KettleValueException) to identify the offending row/field via row logging.

Example fix

// before (partitioning on a string field directly)
partitioner.setFieldName("order_id_text");

// after (convert to Integer before the partitioned step)
// Add a Calculator/SelectValues step: order_id_text -> Integer order_id
partitioner.setFieldName("order_id");
Defensive patterns

Strategy: validation

Validate before calling

// Java: validate partition field before putRow
Object val = row[getFieldIndex(rowMeta, "partitionField")];
if (val == null || !(val instanceof Number) ) {
  throw new IllegalArgumentException("partitionField must be a numeric integer");
}

Type guard

boolean isValidPartitionValue(Object v) {
  return v instanceof Integer || (v instanceof Number && ((Number) v).doubleValue() == Math.floor(((Number) v).doubleValue()));
}

Try / catch

try {
  putRow(rowMeta, row);
} catch (KettleStepException e) {
  if (e.getMessage().contains("Unable to convert a value to integer")) {
    logError("Bad partition key in row: " + Arrays.toString(row), e);
    // route to error handling or skip
  } else { throw e; }
}

Prevention

When it happens

Trigger: A step is partitioned (e.g. mod partitioning) across multiple copies and the field used as the partitioning key contains a non-integer value (string text, null handling, decimal, or out-of-range number) for the current row, so getPartition() throws while converting it to int.

Common situations: Partitioning on a String field that contains text instead of numbers; using a field with a different type than expected after an upstream step changed metadata; partitioning on a Number field with fractional values; nulls or locale-formatted numbers.

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/927dd6c907384177. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/step/BaseStep.java:1379

  private void specialPartitioning( RowMetaInterface rowMeta, Object[] row ) throws KettleStepException {
    if ( nextStepPartitioningMeta == null ) {
      // Look up the partitioning of the next step.
      // This is the case for non-clustered partitioning...
      //
      List<StepMeta> nextSteps = transMeta.findNextSteps( stepMeta );
      if ( nextSteps.size() > 0 ) {
        nextStepPartitioningMeta = nextSteps.get( 0 ).getStepPartitioningMeta();
      }

      // TODO: throw exception if we're not partitioning yet.
      // For now it throws a NP Exception.
    }

    int partitionNr;
    try {
      partitionNr = nextStepPartitioningMeta.getPartition( rowMeta, row );
    } catch ( KettleException e ) {
      throw new KettleStepException(
        "Unable to convert a value to integer while calculating the partition number", e );
    }

    RowSet selectedRowSet = null;

    if ( clusteredPartitioningFirst ) {
      clusteredPartitioningFirst = false;

      // We are only running remotely if both the distribution is there AND if the distribution is actually contains
      // something.
      //
      clusteredPartitioning =
        transMeta.getSlaveStepCopyPartitionDistribution() != null
          && !transMeta.getSlaveStepCopyPartitionDistribution().getDistribution().isEmpty();
    }

    // OK, we have a SlaveStepCopyPartitionDistribution in the transformation...
    // We want to pre-calculate what rowset we're sending data to for which partition...

View on GitHub (pinned to f3058517a1)