apache/pulsar · error · RuntimeException

Message payload processor class does not have constructor ac

Error message

Message payload processor class does not have constructor accepts map

What it means

Mirror case of the missing default constructor: when a non-empty configs map is supplied, getMessagePayloadProcessorInstance looks for a constructor accepting Map; a NoSuchMethodException there is rethrown as this RuntimeException.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/MessagePayloadProcessorUtils.java:57

            payloadProcessorClass = ClassLoaderUtils.loadClass(className, classLoader);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(
                    String.format("Failed to load message payload processor class %sx", className));
        }

        try {
            if (configs == null || configs.isEmpty()) {
                Constructor<?> ctor = payloadProcessorClass.getConstructor();
                return (MessagePayloadProcessor) ctor.newInstance();
            } else {
                Constructor<?> ctor = payloadProcessorClass.getConstructor(Map.class);
                return (MessagePayloadProcessor) ctor.newInstance(configs);
            }
        } catch (NoSuchMethodException e) {
            if (configs == null || configs.isEmpty()) {
                throw new RuntimeException("Message payload processor class does not have default constructor", e);
            } else {
                throw new RuntimeException("Message payload processor class does not have constructor accepts map", e);
            }
        } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
            throw new RuntimeException("Failed to create instance for message payload processor class", e);
        }
    }

    public static MessagePayloadProcessorConfig convertFromSpec(MessagePayloadProcessorSpec spec) {
        if (spec == null || isEmpty(spec.getClassName())) {
            return null;
        }

        MessagePayloadProcessorConfig.MessagePayloadProcessorConfigBuilder bldr =
                MessagePayloadProcessorConfig.builder();

        Type type = new TypeToken<Map<String, Object>>() {
        }.getType();
        Map<String, Object> configs = new Gson().fromJson(spec.getConfigs(), type);

View on GitHub (pinned to 820761864e)

Solutions

  1. Add a public constructor accepting java.util.Map to the processor class
  2. Or remove/clear the configs in the spec so the no-arg constructor path is used
  3. Ensure the constructor's parameter is exactly Map (getConstructor(Map.class)) — not a subtype or different generic erasure

Example fix

// before
public MyProcessor() { }
// after
public MyProcessor(Map<String, Object> configs) {
  this.timeoutMs = (int) configs.getOrDefault("timeoutMs", 30000);
}
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> c = Class.forName(className, false, cl);
boolean ok;
try { c.getConstructor(Map.class); ok = true; } catch (NoSuchMethodException e) { ok = false; }
if (!ok && configs != null && !configs.isEmpty()) {
  throw new IllegalStateException(className + " needs a public Map constructor when configs are set");
}

Type guard

boolean hasMapCtor(Class<?> c) {
  try { c.getConstructor(Map.class); return true; } catch (NoSuchMethodException e) { return false; }
}

Try / catch

try {
  createFunction(...);
} catch (RuntimeException e) {
  if ("Message payload processor class does not have constructor accepts map".equals(e.getMessage())) {
    log.error("Add MyProcessor(Map<String,Object>) to {}", className);
  }
}

Prevention

When it happens

Trigger: Function spec passes non-empty configs for messagePayloadProcessor, but the processor class has no public constructor taking a single Map argument (only a default constructor, or a different signature).

Common situations: Configs added in the function spec after the class was written with only a no-arg constructor; config keys passed as a Map<String,String> expectation mismatch (signature must be Map.class); wrong class configured.

Related errors


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