apache/pulsar · error · IllegalArgumentException

MessagePayloadProcessor class name required

Error message

MessagePayloadProcessor class name required

What it means

When an InputSpec defines a MessagePayloadProcessorConfig, its className must be a non-blank string identifying the payload processor implementation. A null/empty class name leaves the processor unresolvable, so validation throws IllegalArgumentException('MessagePayloadProcessor class name required').

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:929

                throw new IllegalArgumentException("The supplied go file does not exist");
            }
        }

        if (functionConfig.getInputSpecs() != null) {
            functionConfig.getInputSpecs().forEach((topicName, conf) -> {
                // receiver queue size should be >= 0
                if (conf.getReceiverQueueSize() != null && conf.getReceiverQueueSize() < 0) {
                    throw new IllegalArgumentException(
                        "Receiver queue size should be >= zero");
                }

                if (conf.getCryptoConfig() != null && isBlank(conf.getCryptoConfig().getCryptoKeyReaderClassName())) {
                    throw new IllegalArgumentException(
                            "CryptoKeyReader class name required");
                }
                if (conf.getMessagePayloadProcessorConfig() != null && isBlank(
                        conf.getMessagePayloadProcessorConfig().getClassName())) {
                    throw new IllegalArgumentException(
                            "MessagePayloadProcessor class name required");
                }
            });
        }

        if (functionConfig.getProducerConfig() != null
                && functionConfig.getProducerConfig().getCryptoConfig() != null) {
            if (isBlank(functionConfig.getProducerConfig().getCryptoConfig().getCryptoKeyReaderClassName())) {
                throw new IllegalArgumentException("CryptoKeyReader class name required");
            }

            if (functionConfig.getProducerConfig().getCryptoConfig().getEncryptionKeys() == null
                    || functionConfig.getProducerConfig().getCryptoConfig().getEncryptionKeys().length == 0) {
                throw new IllegalArgumentException("Must provide encryption key name for crypto key reader");
            }
        }
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the fully qualified implementation class name: messagePayloadProcessorConfig.setClassName("com.example.MyPayloadProcessor")
  2. Ensure the processor class is packaged and loadable by the function worker
  3. If payload processing is not required for that topic, remove the MessagePayloadProcessorConfig from the InputSpec
  4. Verify the config file/templating actually populates the className field

Example fix

// before
MessagePayloadProcessorConfig ppc = new MessagePayloadProcessorConfig();
inputSpec.setMessagePayloadProcessorConfig(ppc); // className null
// after
MessagePayloadProcessorConfig ppc = new MessagePayloadProcessorConfig();
ppc.setClassName("com.example.MyPayloadProcessor");
inputSpec.setMessagePayloadProcessorConfig(ppc);
Defensive patterns

Strategy: validation

Validate before calling

MessagePayloadProcessorConfig ppc = spec.getMessagePayloadProcessorConfig();
if (ppc != null && (ppc.getClassName() == null || ppc.getClassName().isBlank())) {
    throw new IllegalStateException("MessagePayloadProcessor className required");
}

Type guard

boolean hasPayloadProcessorClass(MessagePayloadProcessorConfig c) {
    return c == null || (c.getClassName() != null && !c.getClassName().isBlank());
}

Try / catch

try {
    admin.functions().createFunction(conf);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("MessagePayloadProcessor class name")) {
        spec.getMessagePayloadProcessorConfig().setClassName(DEFAULT_PROCESSOR_CLASS);
        admin.functions().createFunction(conf);
    } else throw e;
}

Prevention

When it happens

Trigger: Setting InputSpec.setMessagePayloadProcessorConfig(new MessagePayloadProcessorConfig()) or one whose getClassName() is empty/whitespace, then validating the function config (create/update path).

Common situations: Constructing the processor config object without filling in the class name; YAML/JSON payload-processor block present but className key missing; placeholder like '${processorClass}' unresolved; copy of sample config where className line was deleted.

Related errors


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