apache/iceberg · error · IllegalArgumentException
The Avro schema is not a nullable type:
Error message
The Avro schema is not a nullable type:
What it means
convert throws IllegalArgumentException when the provided Avro Schema is a union that is not a simple nullable type (exactly [T, null] or [null, T]). The code resolves a two-element union to its non-null member but cannot handle wider unions or unions whose second member is not NULL.
Source
Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/formats/avro/RowDataToAvroConverters.java:292
private static final long serialVersionUID = 1L;
@Override
public Object convert(Schema schema, Object object) {
if (object == null) {
return null;
}
// get actual schema if it is a nullable schema
Schema actualSchema;
if (schema.getType() == Schema.Type.UNION) {
List<Schema> types = schema.getTypes();
int size = types.size();
if (size == 2 && types.get(1).getType() == Schema.Type.NULL) {
actualSchema = types.get(0);
} else if (size == 2 && types.get(0).getType() == Schema.Type.NULL) {
actualSchema = types.get(1);
} else {
throw new IllegalArgumentException(
"The Avro schema is not a nullable type: " + schema.toString());
}
} else {
actualSchema = schema;
}
return converter.convert(actualSchema, object);
}
};
}
private static RowDataToAvroConverter createRowConverter(
RowType rowType, boolean legacyTimestampMapping) {
final RowDataToAvroConverter[] fieldConverters =
rowType.getChildren().stream()
.map(legacyType -> createConverter(legacyType, legacyTimestampMapping))
.toArray(RowDataToAvroConverter[]::new);
final LogicalType[] fieldTypes =
rowType.getFields().stream().map(RowType.RowField::getType).toArray(LogicalType[]::new);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Flatten the Avro schema so each field is either a single type or a [T, null] union
- Normalize upstream schema generation to standard nullable unions only
- Preprocess the schema to branch on all union members before calling this converter
Example fix
// before "type": ["null", "int", "string"] — throws // after "type": ["null", "int"]
Defensive patterns
Strategy: validation
Validate before calling
if (schema.getType() == Schema.Type.UNION && schema.getTypes().size() != 2) { throw new IllegalArgumentException("Only nullable [T, null] unions are supported: " + schema); } Type guard
boolean isNullableUnion(Schema s) { return s.getType() != Schema.Type.UNION || (s.getTypes().size() == 2 && s.getTypes().stream().anyMatch(t -> t.getType() == Schema.Type.NULL)); } Try / catch
try { return convert(schema, object); } catch (IllegalArgumentException e) { throw new IllegalStateException("Widen the nullable-union handling or fix the schema: " + e.getMessage(), e); } Prevention
- Generate Avro schemas with only [T, null] optional fields
- Validate schemas from the registry against this constraint at startup
- Normalize third-party schemas before feeding them to the converter
When it happens
Trigger: Writing a RowData field whose Avro schema is a union of three or more types, or a union like [int, string]; the nullable-unwrapping path requires exactly one non-null branch plus NULL.
Common situations: Avro schemas produced by other tools with rich unions (e.g. optional fields with default unions of multiple types); schema registry schemas carrying [null, T, U].
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
- The Avro schema is not a nullable type: ${schema.toString()}
- Unsupported logical type: ${logicalType}
- The Avro schema is not a nullable type: ${schema}
- Unsupported Avro type '${schema.getType()}'.
- Invalid primary key '%s'. A primary key must not contain dup
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/9df6ab718f18eabf.
Report an issue: GitHub.