pentaho/pentaho-kettle · error · KettleStepException

Calculator.Error.UnableFindField

Calculator.Error.UnableFindField

Error message

Calculator.Error.UnableFindField

What it means

The Calculator step resolves each calculation function's source field name against the incoming row metadata via indexOfValue. When the field name is non-empty but the lookup returns a negative index, the field does not exist in the input rows, so processRow throws KettleStepException with the localized message Calculator.Error.UnableFindField, including the field name and 1-based calculation number.

Solutions

  1. Fix the 'Field name' in the failing calculation (shown as #N in the message) to match an existing input field
  2. Re-select the field using the dropdown/'Get fields' so it matches the current upstream layout
  3. Insert or restore the step that produces the missing field before the Calculator

Example fix

// before
function.setFieldName("totalAmount"); // upstream field is "total_amt"
// after
function.setFieldName("total_amt");
Defensive patterns

Strategy: validation

Validate before calling

for (int i = 0; i < meta.getCalculationFunctions().size(); i++) {
  CalculatorMetaFunction fn = meta.getCalculationFunctions().get(i);
  if (!Utils.isEmpty(fn.getFieldName()) && calcRowMeta.indexOfValue(fn.getFieldName()) < 0)
    throw new IllegalArgumentException("Calc #" + (i+1) + " references missing field: " + fn.getFieldName());
}

Type guard

boolean calcFieldResolvable(RowMetaInterface row, CalculatorMetaFunction fn) { return Utils.isEmpty(fn.getFieldName()) || row.indexOfValue(fn.getFieldName()) >= 0; }

Try / catch

try { processRow-like init; } catch (KettleStepException e) { if (e.getMessage().contains("Unable to find field")) { /* correct the field in step settings */ } throw e; }

Prevention

When it happens

Trigger: processRow, during first-row initialization: function.getFieldName() is non-empty but data.getCalcRowMeta().indexOfValue(fieldName) < 0 — i.e. a configured calculation references a field not present in the input stream.

Common situations: Renaming an upstream field without updating the Calculator; connecting the Calculator after a step that drops the field; typing the field name manually instead of using the field picker.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/trans/steps/calculator/Calculator.java:97

      // get all metadata, including source rows and temporary fields.
      data.setCalcRowMeta( meta.getAllFields( getInputRowMeta() ) );

      data.setFieldIndexes( new FieldIndexes[meta.getCalculation().length] );
      List<Integer> tempIndexes = new ArrayList<Integer>();

      // Calculate the indexes of the values and arguments in the target data or temporary data
      // We do this in advance to save time later on.
      //
      //CHECKSTYLE:Indentation:OFF
      for ( int i = 0; i < meta.getCalculation().length; i++ ) {
        CalculatorMetaFunction function = meta.getCalculation()[i];
        data.getFieldIndexes()[i] = new FieldIndexes();

        if ( !Utils.isEmpty( function.getFieldName() ) ) {
          data.getFieldIndexes()[i].indexName = data.getCalcRowMeta().indexOfValue( function.getFieldName() );
          if ( data.getFieldIndexes()[i].indexName < 0 ) {
            // Nope: throw an exception
            throw new KettleStepException( BaseMessages.getString(
              PKG, "Calculator.Error.UnableFindField", function.getFieldName(), "" + ( i + 1 ) ) );
          }
        } else {
          throw new KettleStepException( BaseMessages.getString( PKG, "Calculator.Error.NoNameField", ""
            + ( i + 1 ) ) );
        }

        if ( !Utils.isEmpty( function.getFieldA() ) ) {
          if ( function.getCalcType() != CalculatorMetaFunction.CALC_CONSTANT ) {
            data.getFieldIndexes()[i].indexA = data.getCalcRowMeta().indexOfValue( function.getFieldA() );
            if ( data.getFieldIndexes()[i].indexA < 0 ) {
              // Nope: throw an exception
              throw new KettleStepException( "Unable to find the first argument field '"
                + function.getFieldName() + " for calculation #" + ( i + 1 ) );
            }
          } else {
            data.getFieldIndexes()[i].indexA = -1;
          }

View on GitHub (pinned to f3058517a1)