apache/pulsar · error · IllegalArgumentException
The input serialization/deserialization class %s does not ex
Error message
The input serialization/deserialization class %s does not exist
What it means
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.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/ValidatorUtils.java:150
throw new IllegalArgumentException(
String.format("The message payload processor class %s does not implement the desired constructor.",
conf.getClassName()));
}
}
public static void validateSerde(String inputSerializer, TypeDefinition typeArg, TypePool typePool,
boolean deser) {
if (isEmpty(inputSerializer)) {
return;
}
if (inputSerializer.equals(DEFAULT_SERDE)) {
return;
}
TypeDescription serdeClass;
try {
serdeClass = typePool.describe(inputSerializer).resolve();
} catch (TypePool.Resolution.NoSuchTypeException e) {
throw new IllegalArgumentException(
String.format("The input serialization/deserialization class %s does not exist",
inputSerializer));
}
TypeDescription.Generic serDeTypeArg = serdeClass.getInterfaces().stream()
.filter(i -> i.asErasure().isAssignableTo(SerDe.class))
.findFirst()
.map(i -> i.getTypeArguments().get(0))
.orElseThrow(() -> new IllegalArgumentException(
String.format("%s does not implement %s", inputSerializer, SerDe.class.getName())));
if (deser) {
if (!serDeTypeArg.asErasure().isAssignableTo(typeArg.asErasure())) {
throw new IllegalArgumentException("Serializer type mismatch " + typeArg.getActualName() + " vs "
+ serDeTypeArg.getActualName());
}
} else {
if (!serDeTypeArg.asErasure().isAssignableFrom(typeArg.asErasure())) {
throw new IllegalArgumentException("Serializer type mismatch " + typeArg.getActualName() + " vs "View on GitHub (pinned to 820761864e)
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).
Example fix
// before (class renamed, config stale) --inputs-serde com.example.serde.OldEventSerde // after --inputs-serde com.example.serde.EventSerde (class repackaged in the function jar)
Defensive patterns
Strategy: validation
Validate before calling
static boolean serdeExists(String serdeClass, ClassLoader cl) {
if (serdeClass == null || serdeClass.isEmpty()
|| "org.apache.pulsar.functions.api.utils.DefaultSerDe".equals(serdeClass)) return true;
try { Class.forName(serdeClass, false, cl); return true; }
catch (ClassNotFoundException e) { return false; }
} Try / catch
try {
validateSerde(inputSerializer, typeArg, typePool, deser);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("does not exist")) {
throw new IllegalStateException("SerDe class not on classpath: " + inputSerializer
+ " — check the FQCN and that it is packaged in the function jar", e);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Config class not found: %s
- Serializer type mismatch
- Serializer type mismatch ${typeArg} vs ${serDeTypeArg}
- Failed to load an authorization provider.
- No java.security.Provider named '${name}' could be resolved
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/34d18d60689f3510.
Report an issue: GitHub.