apache/pulsar · error · IllegalArgumentException

The message payload processor class

Error message

The message payload processor class %s does not exist

What it means

validateMessagePayloadProcessor resolves conf.getClassName() via a ByteBuddy TypePool; when the named MessagePayloadProcessor class cannot be found on the classpath (NoSuchTypeException) this IllegalArgumentException is thrown. The payload processor handles BatchSource payload decoding (e.g. Avro, Parquet).

Solutions

  1. Correct the className in the payload processor config
  2. Package the MessagePayloadProcessor implementation into the submitted jar
  3. Use a processor class confirmed to exist in your Pulsar version (check the org.apache.pulsar.functions.utils.collections / processor packages for your release)

Example fix

// before
// className: com.acme.OldProcessor // removed in this Pulsar version
// after
// className: org.apache.pulsar.functions.avro.AvroPayloadProcessor // exists in classpath
Defensive patterns

Strategy: validation

Validate before calling

try {
    Class.forName(conf.getClassName());
} catch (ClassNotFoundException e) {
    throw new IllegalStateException("Payload processor class missing: " + conf.getClassName());
}

Try / catch

try {
    ValidatorUtils.validateMessagePayloadProcessor(conf, typePool);
} catch (IllegalArgumentException e) {
    if (e.getMessage().endsWith("does not exist")) {
        // correct className or package the processor class
    }
    throw e;
}

Prevention

When it happens

Trigger: Configuring a MessagePayloadProcessorConfig with a className that is missing from the function jar or worker classpath, or a typo in the FQCN.

Common situations: Referencing a built-in processor class (e.g. AvroPayloadProcessor) that is not shipped with the worker version; custom processor jar not uploaded; package renamed across Pulsar releases.

Related errors


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

Appendix: source

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

                            conf.getCryptoKeyReaderClassName()));
        }

        if (isProducer && (conf.getEncryptionKeys() == null || conf.getEncryptionKeys().length == 0)) {
            throw new IllegalArgumentException("Missing encryption key name for producer crypto key reader");
        }
    }

    public static void validateMessagePayloadProcessor(MessagePayloadProcessorConfig conf, TypePool typePool) {
        if (isEmpty(conf.getClassName())) {
            return;
        }

        String payloadProcessorClassName = conf.getClassName();
        TypeDescription payloadProcessorClass = null;
        try {
            payloadProcessorClass = typePool.describe(payloadProcessorClassName).resolve();
        } catch (TypePool.Resolution.NoSuchTypeException e) {
            throw new IllegalArgumentException(
                    String.format("The message payload processor class %s does not exist", payloadProcessorClassName));
        }
        if (!payloadProcessorClass.asErasure().isAssignableTo(MessagePayloadProcessor.class)) {
            throw new IllegalArgumentException(String.format("%s does not implement %s", payloadProcessorClassName,
                    MessagePayloadProcessor.class.getName()));
        }

        boolean hasConstructor;
        if (conf.getConfig() == null || conf.getConfig().isEmpty()) {
            hasConstructor = payloadProcessorClass.getDeclaredMethods().stream()
                    .anyMatch(method -> method.isConstructor() && method.getParameters().size() == 0);
        } else {
            hasConstructor = payloadProcessorClass.getDeclaredMethods().stream()
                    .anyMatch(method -> method.isConstructor() && method.getParameters().size() == 1
                            && method.getParameters().get(0).getType().asErasure().represents(Map.class));
        }

        if (!hasConstructor) {

View on GitHub (pinned to 820761864e)