apache/beam · error · IllegalArgumentException
FieldType must be either a row or a container containing…
Error message
FieldType <type> must be either a row or a container containing rows
What it means
FieldAccessDescriptor.getFieldSchema recursively descends a FieldType to find the nested row schema it references. It accepts rows, containers of rows, map value types, and logical-type base types; anything else has no row schema and triggers this IllegalArgumentException. It means a field-selection qualifier navigated into a type that has no schema to select from.
Solutions
- Fix the field-access qualifier so nested selection only traverses row-typed (or row-container) fields.
- Validate the target Schema field types before resolving the descriptor.
- If the underlying schema changed, update FieldAccessDescriptor usage to match the new structure.
- Catch IllegalArgumentException from resolve() and report a user-facing schema-mapping error.
Example fix
// before: 'user.name' where user is STRING
FieldAccessDescriptor.withFieldNames("user.name")
// after: select only existing row fields
FieldAccessDescriptor.withFieldNames("user") Defensive patterns
Strategy: validation
Validate before calling
Schema.Field f = schema.getField("user");
if (!f.getType().getTypeName().isCompositeType() && f.getType().getTypeName() != Schema.TypeName.ROW)
throw new IllegalArgumentException("field 'user' is not row-typed; cannot select nested fields"); Type guard
static boolean isRowNavigable(FieldType t) {
return t.getTypeName() == TypeName.ROW || t.getTypeName() == TypeName.ARRAY || t.getTypeName() == TypeName.ITERABLE || t.getTypeName() == TypeName.MAP || t.getTypeName() == TypeName.LOGICAL_TYPE;
} Try / catch
try { descriptor.resolve(schema); }
catch (IllegalArgumentException e) {
if (e.getMessage().contains("must be either a row or a container")) {
throw new IllegalArgumentException("Field selection navigates into a non-row field; fix qualifier", e);
} throw e;
} Prevention
- Keep field-selection strings in sync with the schema definition
- Validate descriptors in unit tests against the actual schema
- Avoid over-navigating qualifiers into primitive fields
When it happens
Trigger: Calling FieldAccessDescriptor.withFieldNames/withMatchingFields resolved against a schema where the accessed field (after container/logical unwrapping) is a primitive — e.g. selecting nested fields 'a.b' where a is an INT64, or indexing into a container of primitives.
Common situations: Schema field selection strings that over-navigate (field[0].x on List<String>); schema drift after changing a field from a row to a primitive; using getFieldSchema directly on a leaf FieldType.
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
- Invalid field id for schema
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
- apache_beam.io.gcp.datastore.v1new.datastoreio.Entity…
- apache_beam.io.gcp.datastore.v1new.datastoreio.Key…
- append() only accepts DeferredDataFrame instances, received
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/e13adaeeb2cfdb70.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/FieldAccessDescriptor.java:616
fieldType = fieldType.getCollectionElementType();
} else if (fieldType.getTypeName().isMapType()) {
fieldType = fieldType.getMapValueType();
}
}
return getFieldSchema(fieldType);
}
private static Schema getFieldSchema(FieldType type) {
if (TypeName.ROW.equals(type.getTypeName())) {
return type.getRowSchema();
} else if (type.getTypeName().isCollectionType()) {
return getFieldSchema(type.getCollectionElementType());
} else if (TypeName.MAP.equals(type.getTypeName())) {
return getFieldSchema(type.getMapValueType());
} else if (TypeName.LOGICAL_TYPE.equals(type.getTypeName())) {
return getFieldSchema(type.getLogicalType().getBaseType());
} else {
throw new IllegalArgumentException(
"FieldType " + type + " must be either a row or a container containing rows");
}
}
private static void validateFieldDescriptor(Schema schema, FieldDescriptor fieldDescriptor) {
Integer fieldId = fieldDescriptor.getFieldId();
if (fieldId != null) {
if (fieldId < 0 || fieldId >= schema.getFieldCount()) {
throw new IllegalArgumentException("Invalid field id " + fieldId + " for schema " + schema);
}
}
// If qualifiers were specified, validate them.
// For example, if a selector was a[*][*], then a needs to be a List of a List.
Field field =
(fieldId != null)
? schema.getField(fieldId)
: schema.getField(fieldDescriptor.getFieldName());
FieldType fieldType = field.getType();View on GitHub (pinned to 12126d8942)