apache/pulsar · error · IllegalArgumentException

%s does not implement %s

Error message

%s does not implement %s

What it means

After resolving the schemaType class successfully, validateSchema checks with ByteBuddy that it is assignable to org.apache.pulsar.client.api.Schema. If the class exists but does not implement Schema, this IllegalArgumentException is thrown naming the class and required interface.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java:53

@CustomLog
public class ValidatorUtils {
    private static final String DEFAULT_SERDE = "org.apache.pulsar.functions.api.utils.DefaultSerDe";

    public static void validateSchema(String schemaType, TypeDefinition typeArg, TypePool typePool,
                                      boolean input) {
        if (isEmpty(schemaType) || getBuiltinSchemaType(schemaType) != null) {
            // If it's empty, we use the default schema and no need to validate
            // If it's built-in, no need to validate
        } else {
            TypeDescription schemaClass = null;
            try {
                schemaClass = typePool.describe(schemaType).resolve();
            } catch (TypePool.Resolution.NoSuchTypeException e) {
                throw new IllegalArgumentException(
                        String.format("The schema class %s does not exist", schemaType));
            }
            if (!schemaClass.asErasure().isAssignableTo(Schema.class)) {
                throw new IllegalArgumentException(
                        String.format("%s does not implement %s", schemaType, Schema.class.getName()));
            }
            validateSchemaType(schemaClass, typeArg, typePool, input);
        }
    }

    private static SchemaType getBuiltinSchemaType(String schemaTypeOrClassName) {
        try {
            return SchemaType.valueOf(schemaTypeOrClassName.toUpperCase());
        } catch (IllegalArgumentException e) {
            // schemaType is not referring to builtin type
            return null;
        }
    }


    public static void validateCryptoKeyReader(CryptoConfig conf, TypePool typePool, boolean isProducer) {
        if (isEmpty(conf.getCryptoKeyReaderClassName())) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Implement org.apache.pulsar.client.api.Schema (or extend SchemaBase / use SchemaBuilder) in the custom class
  2. Point schema-type at the Schema implementation class, not the data class
  3. Use a built-in schema type instead of a custom class

Example fix

// before
// schema-type: com.acme.UserRecord  // POJO, does not implement Schema
// after
public class UserRecordSchema implements Schema<UserRecord> {
    @Override public UserRecord decode(byte[] bytes) { ... }
    @Override public byte[] encode(UserRecord obj) { ... }
}
// schema-type: com.acme.UserRecordSchema
Defensive patterns

Strategy: type-guard

Validate before calling

if (!org.apache.pulsar.client.api.Schema.class.isAssignableFrom(Class.forName(schemaType))) {
    throw new IllegalStateException(schemaType + " is not a Schema implementation");
}

Type guard

static boolean isPulsarSchema(Class<?> c) {
    return c != null && org.apache.pulsar.client.api.Schema.class.isAssignableFrom(c);
}

Try / catch

try {
    ValidatorUtils.validateSchema(schemaType, typeArg, typePool, input);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("does not implement")) {
        // point schema-type at a class implementing org.apache.pulsar.client.api.Schema
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring schema-type with the FQCN of a class that compiles and is on the classpath but does not implement the Schema interface (e.g. an Avro POJO, a DTO, or a helper class passed by mistake).

Common situations: Passing the record/POJO class instead of its Schema wrapper; implementing a similarly named custom interface instead of org.apache.pulsar.client.api.Schema; copy-pasting the wrong class name from another project.

Related errors


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