{"record":{"id":"54a50535c06f290e","repo":"apache/flink","slug":"avro-union-with-null-type-is-only-supported-unsup","errorCode":null,"errorMessage":"Avro Union with NULL type is only supported. Unsupported types: {}","messagePattern":"Avro Union with NULL type is only supported\\. Unsupported types: (.+?)","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-avro/src/main/java/org/apache/flink/formats/avro/AvroToVariantDataConverters.java","lineNumber":155,"sourceCode":"                        createNullableConverter(elementSchema);\n                return createArrayConverter(elementConverter);\n\n            case MAP:\n                Schema valueSchema = schema.getValueType();\n                AvroToVariantDataConverter valueConverter = createNullableConverter(valueSchema);\n                return createMapConverter(valueConverter);\n\n            case UNION:\n                // Handle nullable types (union with null)\n                List<Schema> nonNullUnionType =\n                        schema.getTypes().stream()\n                                .filter(t -> t.getType() != Schema.Type.NULL)\n                                .collect(Collectors.toList());\n\n                if (nonNullUnionType.size() == 1) {\n                    return createNullableConverter(nonNullUnionType.get(0));\n                } else {\n                    throw new UnsupportedOperationException(\n                            \"Avro Union with NULL type is only supported. Unsupported types: \"\n                                    + schema.getTypes());\n                }\n\n            default:\n                throw new UnsupportedOperationException(\"Unsupported type: \" + schema.getType());\n        }\n    }\n\n    /** Creates an array converter that works directly with Avro elements. */\n    private static AvroToVariantDataConverter createArrayConverter(\n            AvroToVariantDataConverter elementConverter) {\n        return (avroObject) -> {\n            List<?> list = (List<?>) avroObject;\n            VariantBuilder.VariantArrayBuilder variantArrayBuilder = SHARED_BUILDER.array();\n\n            for (Object item : list) {\n                Variant convertedItem = elementConverter.convert(item);","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-avro/src/main/java/org/apache/flink/formats/avro/AvroToVariantDataConverters.java#L137-L173","documentation":"AvroToVariantDataConverters only supports Avro unions of the shape [null, T] or [T, null]. If filtering out NULL branches leaves zero or more than one non-null branch, converter construction throws UnsupportedOperationException listing the full union type list.","triggerScenarios":"An Avro schema field with type [\"null\",\"string\",\"int\"] or any multi-alternative union is converted to Variant; also a union of only nulls (nonNullUnionType.size() != 1).","commonSituations":"Ingesting arbitrary .avsc files (schema-on-read to VARIANT) where unions have 2+ non-null branches; Avro IDL generated from JSON with optional-ish typing; Confluent schemas with complex unions.","solutions":["Restructure the union to at most one non-null branch plus null: [\"null\", T].","Flatten multi-branch unions into a wrapper record or convert them to a single concrete type before the Variant conversion.","If you control the producer, emit VARIANT-native data instead of union-heavy Avro."],"exampleFix":"// before\n{\"name\":\"v\",\"type\":[\"null\",\"string\",\"int\"]}\n\n// after\n{\"name\":\"v\",\"type\":[\"null\",\"string\"]} // pick one concrete branch; encode ints as strings if needed","handlingStrategy":"validation","validationCode":"static void validateUnionForVariant(Schema s) {\n    if (s.getType() == Schema.Type.UNION) {\n        long nonNull = s.getTypes().stream().filter(t -> t.getType() != Schema.Type.NULL).count();\n        if (nonNull != 1) {\n            throw new IllegalArgumentException(\"Union must be [null,T] for VARIANT: \" + s);\n        }\n    }\n}","typeGuard":"static boolean isNullableUnion(Schema s) {\n    return s.getType() == Schema.Type.UNION\n            && s.getTypes().stream().filter(t -> t.getType() != Schema.Type.NULL).count() == 1;\n}","tryCatchPattern":null,"preventionTips":["Lint inbound schemas: unions must have exactly one non-null branch before Variant conversion.","Normalize multi-branch unions upstream (producer side) when possible."],"tags":["avro","flink","variant","union","schema"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}