{"record":{"id":"9df6ab718f18eabf","repo":"apache/iceberg","slug":"the-avro-schema-is-not-a-nullable-type","errorCode":null,"errorMessage":"The Avro schema is not a nullable type: ","messagePattern":"The Avro schema is not a nullable type: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/formats/avro/RowDataToAvroConverters.java","lineNumber":292,"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.toString());\n          }\n        } else {\n          actualSchema = schema;\n        }\n        return converter.convert(actualSchema, object);\n      }\n    };\n  }\n\n  private static RowDataToAvroConverter createRowConverter(\n      RowType rowType, boolean legacyTimestampMapping) {\n    final RowDataToAvroConverter[] fieldConverters =\n        rowType.getChildren().stream()\n            .map(legacyType -> createConverter(legacyType, legacyTimestampMapping))\n            .toArray(RowDataToAvroConverter[]::new);\n    final LogicalType[] fieldTypes =\n        rowType.getFields().stream().map(RowType.RowField::getType).toArray(LogicalType[]::new);","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/formats/avro/RowDataToAvroConverters.java#L274-L310","documentation":"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.","triggerScenarios":"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.","commonSituations":"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].","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"],"exampleFix":"// before\n\"type\": [\"null\", \"int\", \"string\"] — throws\n// after\n\"type\": [\"null\", \"int\"]","handlingStrategy":"validation","validationCode":"if (schema.getType() == Schema.Type.UNION && schema.getTypes().size() != 2) { throw new IllegalArgumentException(\"Only nullable [T, null] unions are supported: \" + schema); }","typeGuard":"boolean isNullableUnion(Schema s) { return s.getType() != Schema.Type.UNION || (s.getTypes().size() == 2 && s.getTypes().stream().anyMatch(t -> t.getType() == Schema.Type.NULL)); }","tryCatchPattern":"try { return convert(schema, object); } catch (IllegalArgumentException e) { throw new IllegalStateException(\"Widen the nullable-union handling or fix the schema: \" + e.getMessage(), e); }","preventionTips":["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"],"tags":["flink","avro","schema","union","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}