{"record":{"id":"9e3902a9cef0b989","repo":"apache/seatunnel","slug":"the-avro-schema-is-not-a-nullable-type-schema","errorCode":null,"errorMessage":"The Avro schema is not a nullable type: ${schema}","messagePattern":"The Avro schema is not a nullable type: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-hudi/src/main/java/org/apache/seatunnel/connectors/seatunnel/hudi/sink/convert/RowDataToAvroConverters.java","lineNumber":224,"sourceCode":"            private static final long serialVersionUID = 1L;\n\n            @Override\n            public Object convert(Schema schema, Object object) {\n                if (object == null) {\n                    return null;\n                }\n\n                // get actual schema if it is a nullable schema\n                Schema actualSchema;\n                if (schema.getType() == Schema.Type.UNION) {\n                    List<Schema> types = schema.getTypes();\n                    int size = types.size();\n                    if (size == 2 && types.get(1).getType() == Schema.Type.NULL) {\n                        actualSchema = types.get(0);\n                    } else if (size == 2 && types.get(0).getType() == Schema.Type.NULL) {\n                        actualSchema = types.get(1);\n                    } else {\n                        throw new IllegalArgumentException(\n                                \"The Avro schema is not a nullable type: \" + schema);\n                    }\n                } else {\n                    actualSchema = schema;\n                }\n                return converter.convert(actualSchema, object);\n            }\n        };\n    }\n\n    private static RowDataToAvroConverter createRowConverter(SeaTunnelRowType rowType) {\n        final RowDataToAvroConverter[] fieldConverters =\n                Arrays.stream(rowType.getFieldTypes())\n                        .map(RowDataToAvroConverters::createConverter)\n                        .toArray(RowDataToAvroConverter[]::new);\n        final SeaTunnelDataType<?>[] fieldTypes = rowType.getFieldTypes();\n\n        return new RowDataToAvroConverter() {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-hudi/src/main/java/org/apache/seatunnel/connectors/seatunnel/hudi/sink/convert/RowDataToAvroConverters.java#L206-L242","documentation":"The nullable-wrapping converter expects an Avro schema that is either a plain type or a union of exactly two types where one is NULL; otherwise it throws IllegalArgumentException because it cannot unwrap the actual schema to delegate conversion.","triggerScenarios":"convert() receives a schema that is a UNION with more than 2 members, or a 2-member union where neither member is NULL (e.g. [string, int]).","commonSituations":"Avro schema generated from Hudi table config with multi-type unions (default values of different types); schema evolution introducing [null, oldType, newType] unions; hand-written Avro schemas not following nullable conventions.","solutions":["Ensure the Avro schema fields are unions of the form [T, null] or [null, T] only","Regenerate/normalize the Hudi table Avro schema so nullable fields use exactly two-branch unions","Simplify multi-branch unions by picking a single type per field"],"exampleFix":"// before: field schema = union(string, int, null)\n// after: field schema = union(string, null)","handlingStrategy":"type-guard","validationCode":"// verify Avro field schemas are two-branch nullable unions\nfor (Schema.Field f : schema.getFields()) {\n    Schema s = f.schema();\n    if (s.getType() == Schema.Type.UNION) {\n        List<Schema> ts = s.getTypes();\n        boolean ok = ts.size() == 2 && (ts.get(0).getType() == Schema.Type.NULL || ts.get(1).getType() == Schema.Type.NULL);\n        if (!ok) throw new IllegalArgumentException(\"Field \" + f.name() + \" union is not [T, null]\");\n    }\n}","typeGuard":"static boolean isTwoBranchNullableUnion(Schema s) {\n    if (s.getType() != Schema.Type.UNION) return false;\n    List<Schema> ts = s.getTypes();\n    return ts.size() == 2 && (ts.get(0).getType() == Schema.Type.NULL || ts.get(1).getType() == Schema.Type.NULL);\n}","tryCatchPattern":"try {\n    converter.convert(schema, value);\n} catch (IllegalArgumentException e) {\n    LOG.error(\"Avro schema not nullable-union shaped: {}\", e.getMessage());\n}","preventionTips":["Generate Hudi table schemas with consistent [null, T] unions","Avoid multi-type unions in schema evolution (single type per field)","Validate Avro schema shape in CI before deploying jobs"],"tags":["hudi","avro","schema","nullable"],"backgroundTag":"schema-validation-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}