pentaho/pentaho-kettle · error · KettleException

AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint

Error message

AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint

What it means

At a non-expansion point the resolved field type was neither RECORD, ARRAY nor MAP — i.e. a primitive was encountered where a nested structure was required to continue path traversal. Primitives are handled by sub-field delegates, so reaching this branch is an invariant violation and AvroNestedReader throws this KettleException.

Solutions

  1. Fix the path definition to stop at the primitive field; let a sub-field delegate read it.
  2. Regenerate/verify the schema so it matches the data's actual nesting.
  3. Check that the correct schema (not an older/newer version) is supplied to the step.
  4. Test the step with a sample record to confirm path/schema alignment.

Example fix

// before: path expects nested object
$.order.items[0].sku
// after: items is now a primitive string id
$.order.items
Defensive patterns

Strategy: validation

Validate before calling

Schema.Type t = resolveType(schema, pathSegments);
if (!EnumSet.of(Schema.Type.RECORD, Schema.Type.ARRAY, Schema.Type.MAP).contains(t)) {
  throw new IllegalStateException("path traverses into primitive: " + t);
}

Try / catch

try {
  rows = reader.avroObjectToKettle(row, space);
} catch (KettleException e) {
  if (e.getMessage().contains("UnexpectedRecordFieldTypeAtNonExpansionPoint")) { routeToErrorStream(row, e); } else throw e;
}

Prevention

When it happens

Trigger: In AvroArrayExpansion.convertToKettleValues, the field's effective Schema.Type (after union unwrapping) is a primitive (STRING, INT, etc.) while remaining path segments still expect a nested container.

Common situations: Configured paths assume nesting (record.array.field) but the actual schema has a scalar at that level; schema evolution replaced a nested structure with a primitive; wrong schema version loaded.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/input/AvroNestedReader.java:1407

            Object[][] result = new Object[ 1 ][ m_outputRowMeta.size() + RowDataUtil.OVER_ALLOCATE_SIZE ];
            return result;
          }
        }
      }

      // what have we got?
      if ( fieldT == Schema.Type.RECORD ) {
        return convertToKettleValues( (GenericData.Record) field, fieldSchema, defaultSchema, space, ignoreMissing );
      } else if ( fieldT == Schema.Type.ARRAY ) {
        return convertToKettleValues( (GenericData.Array) field, fieldSchema, defaultSchema, space, ignoreMissing );
      } else if ( fieldT == Schema.Type.MAP ) {

        return convertToKettleValues( (Map<Utf8, Object>) field, fieldSchema, defaultSchema, space, ignoreMissing );
      } else {
        // primitives will always be handled by the subField delegates, so we
        // should'nt
        // get here
        throw new KettleException( BaseMessages.getString( PKG,
          "AvroInput.Error.UnexpectedRecordFieldTypeAtNonExpansionPoint" ) );
      }
    }
  }

  // ----------------- End AvroArrayExpansion inner class --------------------------------

  /**
   * Converts an incoming row to outgoing format. Extracts fields from either an Avro object in the incoming row or from
   * the next structure in the container or non-container Avro file. May return more than one row if a map/array is
   * being expanded.
   *
   * @param incoming incoming kettle row - may be null if decoding from a file rather than a field
   * @param space    the variables to use
   * @return one or more rows in the outgoing format
   * @throws KettleException if a problem occurs
   */
  public Object[][] avroObjectToKettle( Object[] incoming, VariableSpace space ) throws KettleException {

View on GitHub (pinned to f3058517a1)