{"record":{"id":"2c7f58198271eeb6","repo":"apache/pulsar","slug":"function-in-trigger-function-has-more-than-1-input","errorCode":null,"errorMessage":"Function in trigger function has more than 1 input topics","messagePattern":"Function in trigger function has more than 1 input topics","errorType":"http","errorClass":"RestException","httpStatus":400,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java","lineNumber":1144,"sourceCode":"                    .log(\"Function in trigger function does not exist @ / / /\");\n            throw new RestException(Status.NOT_FOUND, String.format(\"Function %s doesn't exist\", functionName));\n        }\n\n        FunctionMetaData functionMetaData = functionMetaDataManager.getFunctionMetaData(tenant, namespace,\n                functionName);\n\n        String inputTopicToWrite;\n        if (topic != null) {\n            inputTopicToWrite = topic;\n        } else if (functionMetaData.getFunctionDetails().getSource().getInputSpecsCount() == 1) {\n            String[] firstKey = new String[1];\n            functionMetaData.getFunctionDetails().getSource().forEachInputSpecs((k, v) -> firstKey[0] = k);\n            inputTopicToWrite = firstKey[0];\n        } else {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .log(\"Function in trigger function has more than 1 input topics @ / / /\");\n            throw new RestException(Status.BAD_REQUEST, \"Function in trigger function has more than 1 input topics\");\n        }\n        boolean topicFound;\n        try {\n            functionMetaData.getFunctionDetails().getSource().getInputSpecs(inputTopicToWrite);\n            topicFound = true;\n        } catch (IllegalArgumentException e) {\n            topicFound = false;\n        }\n        if (functionMetaData.getFunctionDetails().getSource().getInputSpecsCount() == 0\n                || !topicFound) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .attr(\"topic\", inputTopicToWrite)\n\n                    .log(\"Function in trigger function has unidentified topic @ / / /\");\n            throw new RestException(Status.BAD_REQUEST, \"Function in trigger function has unidentified topic\");\n        }\n        try {","sourceCodeStart":1126,"sourceCodeEnd":1162,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java#L1126-L1162","documentation":"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.","triggerScenarios":"Triggering a function whose FunctionDetails.source.inputSpecs has size > 1 (a multi-topic or topicsPattern source), instead of a single-input function.","commonSituations":"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.","solutions":["Trigger test messages directly on each input topic with a Pulsar producer/reader instead of the trigger endpoint.","Create a temporary single-input test function if the trigger API is required.","Restructure the function to consume one input topic (e.g., fan-in via an intermediate topic) if single-topic triggering is a hard requirement.","Inspect the function's inputSpecs (GET the function config) to confirm it is multi-input."],"exampleFix":"// before: function consumes topicsA and topicsB via inputSpecs{A,B}; calling trigger fails\n// after: test with a producer instead\ntry (Producer<byte[]> p = client.newProducer().topic(\"persistent://public/default/A\").create()) {\n    p.send(\"test\".getBytes());\n}","handlingStrategy":"fallback","validationCode":"static boolean isSingleInput(FunctionConfig cfg) {\n  return cfg.getSource() != null && cfg.getSource().getInputSpecs() != null\n      && cfg.getSource().getInputSpecs().size() == 1;\n}","typeGuard":null,"tryCatchPattern":"if (isSingleInput(cfg)) { trigger(...); }\nelse { // fallback: produce directly to each declared input topic\n  for (String topic : cfg.getSource().getInputSpecs().keySet()) producer.send(topic, payload);\n}","preventionTips":["Detect multi-input functions at test-design time and use direct producers instead","Document that the trigger API supports single-input functions only","Standardize test fixtures on single-topic functions"],"tags":["pulsar-functions","bad-request","rest-api","design-limitation"],"backgroundTag":"unsupported-operation","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}