apache/beam · error · RuntimeException
Unexpected null element type: " + fieldDescriptor.getName()
Error message
Unexpected null element type: " + fieldDescriptor.getName()
What it means
toProtoValue converts Beam values into protobuf values per field. For ARRAY/ITERABLE typed fields it fetches the collection element type with getCollectionElementType(); a null result means the FieldType claims to be a collection but carries no element type, so per-element conversion is impossible and the converter throws, naming the proto field.
Solutions
- Use FieldType.array(elementType) (or FieldType.iterable(elementType)) with a concrete element type.
- Replace raw java.util.List fields in schema classes with generic List<T> so inference captures the element type.
- Validate the schema before the sink: assert getCollectionElementType() != null for all ARRAY/ITERABLE fields.
- Catch the RuntimeException around toProtoValue and fail the record with a clear schema error.
Example fix
// before FieldType arr = FieldType.builder().setType(TypeName.ARRAY).build(); // after FieldType arr = FieldType.array(FieldType.string());
Defensive patterns
Strategy: validation
Validate before calling
for (Schema.Field f : schema.getFields()) {
Schema.FieldType t = f.getType();
if ((t.getTypeName() == Schema.TypeName.ARRAY || t.getTypeName() == Schema.TypeName.ITERABLE)
&& t.getCollectionElementType() == null) {
throw new IllegalArgumentException("Field " + f.getName() + " missing collection element type");
}
} Type guard
boolean hasCollectionElementType(Schema.Field f) {
return (f.getType().getTypeName() != Schema.TypeName.ARRAY
&& f.getType().getTypeName() != Schema.TypeName.ITERABLE)
|| f.getType().getCollectionElementType() != null;
} Try / catch
try {
value = toProtoValue(fieldDescriptor, beamFieldType, v);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Unexpected null element type")) {
throw new SchemaException("Array field lacks element type: " + e.getMessage());
}
throw e;
} Prevention
- Use FieldType.array(elementType), never bare TypeName.ARRAY
- Avoid raw List fields in schema classes
- Validate collection fields during schema construction
When it happens
Trigger: toProtoValue for a field whose beamFieldType.getTypeName() is ARRAY or ITERABLE while beamFieldType.getCollectionElementType() returns null - malformed FieldType built without an element type, or an Iterable typed via reflection without element info.
Common situations: Schemas using Iterable fields inferred from raw/generic Java types (e.g. List without generics), hand-built FieldTypes with TypeName.ARRAY but no collection element, deserialized schemas losing element metadata.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- A function must be provided to convert the input type into…
- BigQueryIO.Write transforms cannot be converted to a…
- Both numFileShards and auto-sharding options are set. Will…
- Both numStorageWriteApiStreams and auto-sharding options…
- Cannot convert BigQuery type '' to '' because the BigQuery…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/52513cf784afc066.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BeamRowToStorageApiProto.java:339
} else {
throw new IllegalArgumentException(
"Received null value for non-nullable field " + fieldDescriptor.getName());
}
}
return toProtoValue(fieldDescriptor, beamField.getType(), value);
}
private static Object toProtoValue(
FieldDescriptor fieldDescriptor, FieldType beamFieldType, Object value) {
switch (beamFieldType.getTypeName()) {
case ROW:
return messageFromBeamRow(fieldDescriptor.getMessageType(), (Row) value, null, -1);
case ARRAY:
case ITERABLE:
Iterable<Object> iterable = (Iterable<Object>) value;
@Nullable FieldType iterableElementType = beamFieldType.getCollectionElementType();
if (iterableElementType == null) {
throw new RuntimeException("Unexpected null element type: " + fieldDescriptor.getName());
}
return StreamSupport.stream(iterable.spliterator(), false)
.map(v -> toProtoValue(fieldDescriptor, iterableElementType, v))
.collect(Collectors.toList());
case MAP:
Map<Object, Object> map = (Map<Object, Object>) value;
@Nullable FieldType keyType = beamFieldType.getMapKeyType();
@Nullable FieldType valueType = beamFieldType.getMapValueType();
if (keyType == null) {
throw new RuntimeException("Unexpected null for key type: " + fieldDescriptor.getName());
}
if (valueType == null) {
throw new RuntimeException(
"Unexpected null for value type: " + fieldDescriptor.getName());
}
return map.entrySet().stream()View on GitHub (pinned to 12126d8942)