apache/pulsar · error · SchemaSerializationException

Unable to create Avro schema for class <pojo.getName()>

Error message

Unable to create Avro schema for class <pojo.getName()>

What it means

extractAvroSchema asks Avro's ReflectData (AllowNull or not) to generate a schema for the given pojo class. If Avro throws a RuntimeException while generating the schema, it is wrapped in a SchemaSerializationException with the class name. This means the class itself is not representable as an Avro schema under reflection.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/schema/util/SchemaUtil.java:110

                validateDefaults.set(savedValidateDefaults);
            }
        } else {
            throw new RuntimeException("Schema definition must specify pojo class or schema json definition");
        }
    }

    public static Schema extractAvroSchema(SchemaDefinition schemaDefinition, Class pojo) {
        try {
            return parseAvroSchema(pojo.getDeclaredField("SCHEMA$").get(null).toString());
        } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException ignored) {
            ReflectData reflectData = schemaDefinition.getAlwaysAllowNull()
                     ? new ReflectData.AllowNull()
                     : new ReflectData();
            AvroSchema.addLogicalTypeConversions(reflectData, schemaDefinition.isJsr310ConversionEnabled(), false);
            try {
                return reflectData.getSchema(pojo);
            } catch (RuntimeException e) {
                throw new SchemaSerializationException(
                        "Unable to create Avro schema for class " + pojo.getName(), e);
            }
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Fix the pojo to be Avro-reflectable: public class, public no-arg constructor, fields of Avro-supported types.
  2. Add @AvroSchemaCompatible / use org.apache.avro.reflect annotations (@AvroIgnore, @AvroEncode) on problematic fields.
  3. Enable JSR310 conversion if using java.time types: SchemaDefinition.builder().withJsr310ConversionEnabled(true).
  4. Alternatively provide the schema as explicit JSON instead of reflection.

Example fix

// before
class Event { private Event() {} private Object payload; }
Schema<Event> s = Schema.AVRO(Event.class);
// after
class Event { public Event() {} private byte[] payload; }
Schema<Event> s = Schema.AVRO(Event.class);
Defensive patterns

Strategy: validation

Validate before calling

boolean avroReflectable(Class<?> c) {
    try {
        c.getDeclaredConstructor().setAccessible(true);
        return !c.isInterface() && !Modifier.isAbstract(c.getModifiers());
    } catch (NoSuchMethodException e) {
        return false; // needs public no-arg constructor
    }
}

Try / catch

try {
    Schema<Event> s = Schema.AVRO(Event.class);
} catch (SchemaSerializationException e) {
    log.error("Pojo not Avro-reflectable: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Schema.AVRO(SomePojo.class) where the pojo has unrepresentable types, is an interface/abstract class, lacks a no-arg constructor, or has fields Avro reflection cannot map (e.g. nested generics Avro cannot handle).

Common situations: Pojo with fields of unsupported types (Object, interfaces, exotic collections); nested pojo missing public no-arg constructor; nullable handling mismatch when allowNull is disabled; JSR310 types without jsr310ConversionEnabled.

Related errors


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