apache/iceberg · error · java.lang.IllegalArgumentException
The Avro schema is not a nullable type: ${schema.toString()}
Error message
The Avro schema is not a nullable type: ${schema.toString()} What it means
During RowDataToAvroConverters.nullable conversion, if the target Avro schema is a union, the code expects exactly two branches with one being NULL (a nullable type). Any other union shape (3+ branches, or two non-null branches) cannot be resolved to a single actual schema and throws this IllegalArgumentException.
Source
Thrown at flink/v2.1/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
- Restructure the Avro schema so nullable fields are unions of exactly one type plus null
- Wrap non-null multi-branch unions into a single record/managed representation before serialization
- Flatten or split the union field into separate columns in the source table
- Validate the Avro schema's unions before wiring it as a sink format
Example fix
// before
{"type":["null","int","string"]}
// after
{"type":["null","string"]} Defensive patterns
Strategy: validation
Validate before calling
Schema fieldSchema = schema.getField("f").schema();
if (fieldSchema.getType() == Schema.Type.UNION) {
List<Schema> branches = fieldSchema.getTypes();
long nulls = branches.stream().filter(s -> s.getType() == Schema.Type.NULL).count();
if (branches.size() != 2 || nulls != 1) {
throw new IllegalStateException("Only [T, null] unions are supported: " + fieldSchema);
}
} Type guard
boolean isSimpleNullableUnion(Schema s) {
if (s.getType() != Schema.Type.UNION) return false;
List<Schema> ts = s.getTypes();
return ts.size() == 2 && ts.stream().anyMatch(b -> b.getType() == Schema.Type.NULL);
} Try / catch
try {
Object avro = converter.convert(schema, row);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("The Avro schema is not a nullable type")) {
// fix or regenerate schema with simple nullable unions
} else { throw e; }
} Prevention
- Generate Avro schemas from table schemas instead of hand-writing unions
- Restrict schemas to [T, null] unions for nullable fields
- Validate schemas with AvroSchemaConverter before production use
- Avoid schema evolution that introduces multi-branch unions
When it happens
Trigger: Serializing RowData into an Avro field whose schema is a union that is not a simple [T, null] or [null, T] pair, e.g. [int, string, null] or [int, long].
Common situations: Hand-written or third-party Avro schemas with multi-branch unions used as Flink sink formats; schemas evolved to add alternative types.
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:
- Unsupported logical type: ${logicalType}
- The Avro schema is not a nullable type: ${schema}
- Unsupported Avro type '${schema.getType()}'.
- Could not parse Avro schema string.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/1494096b4f4d550e.
Report an issue: GitHub.