pentaho/pentaho-kettle · error · KettleRowException

BaseStep.SafeMode.Exception.DoubleFieldnames

BaseStep.SafeMode.Exception.DoubleFieldnames

Error message

BaseStep.SafeMode.Exception.DoubleFieldnames

What it means

During safe-mode validation, BaseStep sorts the incoming row's field names and throws KettleRowException if two adjacent names are equal. Safe mode verifies every row before processing to catch row-layout corruption early. It means the step received a row containing duplicate field names, which makes field lookup ambiguous downstream.

Solutions

  1. Rename one of the duplicate fields in the step that produces them (Select Values / rename in the input step).
  2. In a SQL-based step, alias one of the colliding columns (e.g. SELECT a.id AS a_id, b.id AS b_id).
  3. Enable 'Include row number' with a prefix or use a 'Select values' step to de-duplicate field names before the failing step.
  4. If duplicates are intentional, disable safe mode — but this only hides the ambiguity; downstream steps may still misbehave.

Example fix

// before
fields.add(new ValueMetaString("id"));
fields.add(new ValueMetaString("id")); // duplicate
// after
fields.add(new ValueMetaString("id"));
fields.add(new ValueMetaString("id_2")); // renamed
Defensive patterns

Strategy: validation

Validate before calling

String[] names = rowMeta.getFieldNames();
java.util.Set<String> seen = new java.util.HashSet<>();
for (String n : names) { if (!seen.add(n.toLowerCase())) throw new IllegalStateException("Duplicate field: " + n); }

Try / catch

try { trans.execute(null); } catch (KettleException e) { if (e.getMessage().contains("DoubleFieldnames") || (e.getCause() instanceof KettleRowException && e.getCause().getMessage().contains("double"))) { /* fix input schema */ } else throw e; }

Prevention

When it happens

Trigger: Running a transformation with safe mode enabled; a step emits a RowMeta whose field names contain the exact same name twice (e.g. after two 'putField' calls with the same name, or a join producing 'id' twice).

Common situations: Database joins selecting two columns with the same name without aliases; Excel/CSV inputs where two headers collide; a User Defined Java Expression or Calculator step adding a field whose name already exists.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

   *
   * @param row the row
   * @throws KettleRowException the kettle row exception
   */
  protected void safeModeChecking( RowMetaInterface row ) throws KettleRowException {
    if ( row == null ) {
      return;
    }

    if ( inputReferenceRow == null ) {
      inputReferenceRow = row.clone(); // copy it!

      // Check for double field names.
      //
      String[] fieldnames = row.getFieldNames();
      Arrays.sort( fieldnames );
      for ( int i = 0; i < fieldnames.length - 1; i++ ) {
        if ( fieldnames[ i ].equals( fieldnames[ i + 1 ] ) ) {
          throw new KettleRowException( BaseMessages.getString(
            PKG, "BaseStep.SafeMode.Exception.DoubleFieldnames", fieldnames[ i ] ) );
        }
      }
    } else {
      safeModeChecking( inputReferenceRow, row );
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.pentaho.di.trans.step.StepInterface#identifyErrorOutput()
   */
  @Override
  public void identifyErrorOutput() {
    if ( stepMeta.isDoingErrorHandling() ) {
      StepErrorMeta stepErrorMeta = stepMeta.getStepErrorMeta();
      outputRowSetsLock.writeLock().lock();

View on GitHub (pinned to f3058517a1)