apache/pulsar · error · InvalidSchemaDataException

Avro schema typed [UNION] is not supported

Error message

Avro schema typed [UNION] is not supported

What it means

StructSchemaDataValidator.checkAvroSchemaTypeSupported rejects an Avro schema whose root type is UNION. Pulsar's registry supports RECORD as the root of an Avro schema (plus scalar/array/map special types), but a top-level union cannot be stored as a topic schema. Nested unions inside record fields are fine; only the root union is rejected.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/service/schema/validator/StructSchemaDataValidator.java:95

                // This fallback is only enabled when schemaJsonAllowLegacyJacksonFormat=true (PIP-464).
                try {
                    JSON_SCHEMA_READER.readValue(data);
                } catch (IOException ioe) {
                    throwInvalidSchemaDataException(schemaData, ioe);
                }
            } else {
                throwInvalidSchemaDataException(schemaData, e);
            }
        }
    }

    static void checkAvroSchemaTypeSupported(Schema schema) throws InvalidSchemaDataException {
            switch (schema.getType()) {
                case RECORD: {
                    break;
                }
                case UNION: {
                    throw new InvalidSchemaDataException(
                            "Avro schema typed [UNION] is not supported");
                }
                default: {
                    // INT, LONG, FLOAT, DOUBLE, BOOLEAN, STRING, BYTES.
                    // ARRAY, MAP, FIXED, NULL.
                    LOGGER.info().attr("type", schema.getType()).log("Registering a special avro schema");
                }
            }
    }

    private static void throwInvalidSchemaDataException(SchemaData schemaData,
                                                        Throwable cause) throws InvalidSchemaDataException {
        throw new InvalidSchemaDataException("Invalid schema definition data for "
            + schemaData.getType() + " schema", cause);
    }

    static class CompatibleNameValidator implements NameValidator {

View on GitHub (pinned to 820761864e)

Solutions

  1. Wrap the union in a RECORD: create a top-level record with a single field whose type is the union, and register that record.
  2. Pick one concrete member of the union (typically the record type) and register it as the root schema.
  3. If nullability is the concern, model optional fields as union-typed fields INSIDE the record — nested unions are supported.
  4. Verify locally: new Schema.Parser().parse(json).getType() must not be Type.UNION before uploading.

Example fix

// before
String avro = "[\"null\",{\"type\":\"record\",\"name\":\"User\",\"fields\":[...]}]";
SchemaInfo info = Schema.AVRO(Schema.Parser().parse(avro)).getSchemaInfo();
// after
String avro = "{\"type\":\"record\",\"name\":\"UserRoot\",\"fields\":["
    + "{\"name\":\"user\",\"type\":[\"null\",\"User\"]}]}";
SchemaInfo info = Schema.AVRO(Schema.Parser().parse(avro)).getSchemaInfo();
Defensive patterns

Strategy: validation

Validate before calling

org.apache.avro.Schema avro = new org.apache.avro.Schema.Parser().parse(avroJson);
if (avro.getType() == org.apache.avro.Schema.Type.UNION) {
    throw new IllegalArgumentException("Avro root schema must not be a UNION; wrap it in a RECORD");
}

Type guard

boolean isRegisterableAvroRoot(org.apache.avro.Schema schema) {
    return schema.getType() == org.apache.avro.Schema.Type.RECORD
        || schema.getType() != org.apache.avro.Schema.Type.UNION;
}

Prevention

When it happens

Trigger: Registering an AVRO (or a KEY_VALUE whose side is AVRO) schema parsed from a JSON definition like ["null", {"type":"record",...}] or ["int","string"] — e.g. Schema.AVRO on a generic union, ReflectDatum-generated unions, or hand-written Avro JSON starting with "[".

Common situations: Avro codegen or frameworks producing optional-field root unions; devs using org.apache.avro.Schema unions to represent 'null or record'; copying an Avro field schema (union) instead of the record schema into the registry.

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/e7e4f7983c7959a3. Report an issue: GitHub.