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
- Fix the path definition to stop at the primitive field; let a sub-field delegate read it.
- Regenerate/verify the schema so it matches the data's actual nesting.
- Check that the correct schema (not an older/newer version) is supplied to the step.
- 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
- Design paths to stop at primitives; let sub-field delegates read leaves.
- Re-validate paths whenever the schema changes.
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
- AvroInput.Error.UnexpectedArrayElementTypeAtNonExpansionPoin…
- AvroInput.Error.CantLoadIncommingSchemaAndNoDefault
- AvroInput.Error.EncounteredAPrimitivePriorToMapExpansion
- AvroInput.Error.IncommingSchemaIsMissingAndNoDefault
- AvroInput.Error.MalformedPathArray
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)