apache/pulsar · error · RestException

Function in trigger function has more than 1 input topics

Error message

Function in trigger function has more than 1 input topics

What it means

triggerFunction can only inject a test message into exactly one input topic. If the function's Source declares more than one input topic spec, the worker logs the error and returns HTTP 400 with this message, because it cannot determine which topic to produce to.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java:1144

                    .log("Function in trigger function does not exist @ / / /");
            throw new RestException(Status.NOT_FOUND, String.format("Function %s doesn't exist", functionName));
        }

        FunctionMetaData functionMetaData = functionMetaDataManager.getFunctionMetaData(tenant, namespace,
                functionName);

        String inputTopicToWrite;
        if (topic != null) {
            inputTopicToWrite = topic;
        } else if (functionMetaData.getFunctionDetails().getSource().getInputSpecsCount() == 1) {
            String[] firstKey = new String[1];
            functionMetaData.getFunctionDetails().getSource().forEachInputSpecs((k, v) -> firstKey[0] = k);
            inputTopicToWrite = firstKey[0];
        } else {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .log("Function in trigger function has more than 1 input topics @ / / /");
            throw new RestException(Status.BAD_REQUEST, "Function in trigger function has more than 1 input topics");
        }
        boolean topicFound;
        try {
            functionMetaData.getFunctionDetails().getSource().getInputSpecs(inputTopicToWrite);
            topicFound = true;
        } catch (IllegalArgumentException e) {
            topicFound = false;
        }
        if (functionMetaData.getFunctionDetails().getSource().getInputSpecsCount() == 0
                || !topicFound) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .attr("topic", inputTopicToWrite)

                    .log("Function in trigger function has unidentified topic @ / / /");
            throw new RestException(Status.BAD_REQUEST, "Function in trigger function has unidentified topic");
        }
        try {

View on GitHub (pinned to 820761864e)

Solutions

  1. Trigger test messages directly on each input topic with a Pulsar producer/reader instead of the trigger endpoint.
  2. Create a temporary single-input test function if the trigger API is required.
  3. Restructure the function to consume one input topic (e.g., fan-in via an intermediate topic) if single-topic triggering is a hard requirement.
  4. Inspect the function's inputSpecs (GET the function config) to confirm it is multi-input.

Example fix

// before: function consumes topicsA and topicsB via inputSpecs{A,B}; calling trigger fails
// after: test with a producer instead
try (Producer<byte[]> p = client.newProducer().topic("persistent://public/default/A").create()) {
    p.send("test".getBytes());
}
Defensive patterns

Strategy: fallback

Validate before calling

static boolean isSingleInput(FunctionConfig cfg) {
  return cfg.getSource() != null && cfg.getSource().getInputSpecs() != null
      && cfg.getSource().getInputSpecs().size() == 1;
}

Try / catch

if (isSingleInput(cfg)) { trigger(...); }
else { // fallback: produce directly to each declared input topic
  for (String topic : cfg.getSource().getInputSpecs().keySet()) producer.send(topic, payload);
}

Prevention

When it happens

Trigger: Triggering a function whose FunctionDetails.source.inputSpecs has size > 1 (a multi-topic or topicsPattern source), instead of a single-input function.

Common situations: Functions built from a regex/multi-topic subscription; tests written against a dev function later reconfigured with several inputs; copy-pasting a trigger call from a single-input example onto a multi-input function.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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