{"record":{"id":"34d18d60689f3510","repo":"apache/pulsar","slug":"the-input-serialization-deserialization-class-s-d","errorCode":null,"errorMessage":"The input serialization/deserialization class %s does not exist","messagePattern":"The input serialization/deserialization class (.+?) does not exist","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java","lineNumber":150,"sourceCode":"            throw new IllegalArgumentException(\n                    String.format(\"The message payload processor class %s does not implement the desired constructor.\",\n                            conf.getClassName()));\n        }\n    }\n\n    public static void validateSerde(String inputSerializer, TypeDefinition typeArg, TypePool typePool,\n                                     boolean deser) {\n        if (isEmpty(inputSerializer)) {\n            return;\n        }\n        if (inputSerializer.equals(DEFAULT_SERDE)) {\n            return;\n        }\n        TypeDescription serdeClass;\n        try {\n            serdeClass = typePool.describe(inputSerializer).resolve();\n        } catch (TypePool.Resolution.NoSuchTypeException e) {\n            throw new IllegalArgumentException(\n                    String.format(\"The input serialization/deserialization class %s does not exist\",\n                            inputSerializer));\n        }\n        TypeDescription.Generic serDeTypeArg = serdeClass.getInterfaces().stream()\n                .filter(i -> i.asErasure().isAssignableTo(SerDe.class))\n                .findFirst()\n                .map(i -> i.getTypeArguments().get(0))\n                .orElseThrow(() -> new IllegalArgumentException(\n                        String.format(\"%s does not implement %s\", inputSerializer, SerDe.class.getName())));\n\n        if (deser) {\n            if (!serDeTypeArg.asErasure().isAssignableTo(typeArg.asErasure())) {\n                throw new IllegalArgumentException(\"Serializer type mismatch \" + typeArg.getActualName() + \" vs \"\n                        + serDeTypeArg.getActualName());\n            }\n        } else {\n            if (!serDeTypeArg.asErasure().isAssignableFrom(typeArg.asErasure())) {\n                throw new IllegalArgumentException(\"Serializer type mismatch \" + typeArg.getActualName() + \" vs \"","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java#L132-L168","documentation":"Thrown by ValidatorUtils.validateSerde when the configured serialization/deserialization class name cannot be resolved from the TypePool — i.e. the named class is not on the classpath visible to the validator (TypePool.Resolution.NoSuchTypeException). The validator inspects function config at submission time, before the function is deployed.","triggerScenarios":"Calling validateSerde(inputSerializer, typeArg, typePool, deser) with a non-empty inputSerializer that is not the DefaultSerDe and for which typePool.describe(inputSerializer) throws NoSuchTypeException: wrong fully-qualified class name, class not in the jar searched by the TypePool, or a typo in the package.","commonSituations":"Typing the SerDe class name by hand in function config (typos, wrong package); forgetting to shade the SerDe class into the function's uber jar; renaming or moving the SerDe class during a refactor while old tenant/namespace configs still reference the old name; relying on a class that exists on the broker but not in the submitted function archive.","solutions":["Verify the fully-qualified class name in the function config matches the SerDe class exactly (package + class).","Make sure the class is contained in the function jar/Archive you submit — the TypePool resolves against the submitted artifacts.","Rebuild/redeploy the function package after renaming the SerDe class so the config points at the new name.","If you don't need a custom SerDe, clear the field so validateSerde short-circuits (empty string or DefaultSerDe is allowed)."],"exampleFix":"// before (class renamed, config stale)\n--inputs-serde com.example.serde.OldEventSerde\n// after\n--inputs-serde com.example.serde.EventSerde  (class repackaged in the function jar)","handlingStrategy":"validation","validationCode":"static boolean serdeExists(String serdeClass, ClassLoader cl) {\n    if (serdeClass == null || serdeClass.isEmpty()\n            || \"org.apache.pulsar.functions.api.utils.DefaultSerDe\".equals(serdeClass)) return true;\n    try { Class.forName(serdeClass, false, cl); return true; }\n    catch (ClassNotFoundException e) { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n    validateSerde(inputSerializer, typeArg, typePool, deser);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"does not exist\")) {\n        throw new IllegalStateException(\"SerDe class not on classpath: \" + inputSerializer\n            + \" — check the FQCN and that it is packaged in the function jar\", e);\n    }\n    throw e;\n}","preventionTips":["Reference SerDe classes via their .class.getName() rather than hand-typed strings to avoid typos.","Verify the SerDe is shaded into the function's uber jar before submitting.","Grep configs for old class names after any refactor/rename of SerDe classes."],"tags":["java","pulsar-functions","classpath","serde"],"backgroundTag":"class-not-found","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"}