{"record":{"id":"c8ecb449b489f435","repo":"apache/pulsar","slug":"s-does-not-implement-s-c8ecb4","errorCode":null,"errorMessage":"%s does not implement %s","messagePattern":"(.+?) does not implement (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java","lineNumber":53,"sourceCode":"@CustomLog\npublic class ValidatorUtils {\n    private static final String DEFAULT_SERDE = \"org.apache.pulsar.functions.api.utils.DefaultSerDe\";\n\n    public static void validateSchema(String schemaType, TypeDefinition typeArg, TypePool typePool,\n                                      boolean input) {\n        if (isEmpty(schemaType) || getBuiltinSchemaType(schemaType) != null) {\n            // If it's empty, we use the default schema and no need to validate\n            // If it's built-in, no need to validate\n        } else {\n            TypeDescription schemaClass = null;\n            try {\n                schemaClass = typePool.describe(schemaType).resolve();\n            } catch (TypePool.Resolution.NoSuchTypeException e) {\n                throw new IllegalArgumentException(\n                        String.format(\"The schema class %s does not exist\", schemaType));\n            }\n            if (!schemaClass.asErasure().isAssignableTo(Schema.class)) {\n                throw new IllegalArgumentException(\n                        String.format(\"%s does not implement %s\", schemaType, Schema.class.getName()));\n            }\n            validateSchemaType(schemaClass, typeArg, typePool, input);\n        }\n    }\n\n    private static SchemaType getBuiltinSchemaType(String schemaTypeOrClassName) {\n        try {\n            return SchemaType.valueOf(schemaTypeOrClassName.toUpperCase());\n        } catch (IllegalArgumentException e) {\n            // schemaType is not referring to builtin type\n            return null;\n        }\n    }\n\n\n    public static void validateCryptoKeyReader(CryptoConfig conf, TypePool typePool, boolean isProducer) {\n        if (isEmpty(conf.getCryptoKeyReaderClassName())) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java#L35-L71","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Implement org.apache.pulsar.client.api.Schema (or extend SchemaBase / use SchemaBuilder) in the custom class","Point schema-type at the Schema implementation class, not the data class","Use a built-in schema type instead of a custom class"],"exampleFix":"// before\n// schema-type: com.acme.UserRecord  // POJO, does not implement Schema\n// after\npublic class UserRecordSchema implements Schema<UserRecord> {\n    @Override public UserRecord decode(byte[] bytes) { ... }\n    @Override public byte[] encode(UserRecord obj) { ... }\n}\n// schema-type: com.acme.UserRecordSchema","handlingStrategy":"type-guard","validationCode":"if (!org.apache.pulsar.client.api.Schema.class.isAssignableFrom(Class.forName(schemaType))) {\n    throw new IllegalStateException(schemaType + \" is not a Schema implementation\");\n}","typeGuard":"static boolean isPulsarSchema(Class<?> c) {\n    return c != null && org.apache.pulsar.client.api.Schema.class.isAssignableFrom(c);\n}","tryCatchPattern":"try {\n    ValidatorUtils.validateSchema(schemaType, typeArg, typePool, input);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"does not implement\")) {\n        // point schema-type at a class implementing org.apache.pulsar.client.api.Schema\n    }\n    throw e;\n}","preventionTips":["Always configure the Schema wrapper class, never the data POJO","Compile-time check: declare the custom class as 'implements Schema<T>'","Unit-test schema class resolution with ByteBuddy TypePool before release"],"tags":["pulsar-functions","schema","type-mismatch","bytebuddy"],"backgroundTag":"interface-not-implemented","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}