{"record":{"id":"85462dcb2635ddb2","repo":"apache/pulsar","slug":"input-topic-s-is-invalid","errorCode":null,"errorMessage":"Input topic %s is invalid","messagePattern":"Input topic (.+?) is invalid","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java","lineNumber":812,"sourceCode":"            throw new IllegalArgumentException(\"Function namespace cannot be null\");\n        }\n        if (isEmpty(functionConfig.getName())) {\n            throw new IllegalArgumentException(\"Function name cannot be null\");\n        }\n        // go doesn't need className. Java className is done in doJavaChecks.\n        if (functionConfig.getRuntime() == FunctionConfig.Runtime.PYTHON) {\n            if (isEmpty(functionConfig.getClassName())) {\n                throw new IllegalArgumentException(\"Function classname cannot be null\");\n            }\n        }\n\n        Collection<String> allInputTopics = collectAllInputTopics(functionConfig);\n        if (allInputTopics.isEmpty()) {\n            throw new IllegalArgumentException(\"No input topic(s) specified for the function\");\n        }\n        for (String topic : allInputTopics) {\n            if (!TopicName.isValid(topic)) {\n                throw new IllegalArgumentException(String.format(\"Input topic %s is invalid\", topic));\n            }\n        }\n\n        if (!isEmpty(functionConfig.getOutput())) {\n            if (!TopicName.isValid(functionConfig.getOutput())) {\n                throw new IllegalArgumentException(\n                        String.format(\"Output topic %s is invalid\", functionConfig.getOutput()));\n            }\n        }\n\n        if (!isEmpty(functionConfig.getLogTopic())) {\n            if (!TopicName.isValid(functionConfig.getLogTopic())) {\n                throw new IllegalArgumentException(\n                        String.format(\"LogTopic topic %s is invalid\", functionConfig.getLogTopic()));\n            }\n        }\n\n        if (!isEmpty(functionConfig.getDeadLetterTopic())) {","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java#L794-L830","documentation":"Pulsar Functions validate every configured input topic name before a function is created or updated. This error is thrown by FunctionConfigUtils.doCommonChecks when any topic collected from the function's input list fails TopicName.isValid(), meaning it is not a syntactically valid Pulsar topic name (e.g. missing namespace/tenant components or illegal characters).","triggerScenarios":"Calling createFunction/updateFunction (or submitting a function via CLI, REST admin API, or function mesh manifests) with a FunctionConfig whose input topics include a string that TopicName.isValid rejects: a bare local topic like 'my-topic' without a tenant/namespace, a name with illegal characters or empty segments, or an empty/whitespace string in the input collection.","commonSituations":"Config mistakes such as writing 'persistent://my-tenant/my-ns' with a trailing slash, forgetting the tenant/namespace prefix, copy-pasting topic names with trailing whitespace or newline from YAML/env vars, using Kafka-style names in Pulsar, or typos like double colons in the persistent:// URL.","solutions":["Fix the input topic to a fully qualified Pulsar topic name: [persistent|non-persistent://]<tenant>/<namespace>/<topic>, e.g. persistent://public/default/in-topic","If using a short name, rely on the configured default tenant/namespace instead of passing an invalid bare name","Trim whitespace and remove illegal characters (spaces, empty segments) from the topic string","Verify with org.apache.pulsar.common.naming.TopicName.isValid(topic) in a unit test before deploying"],"exampleFix":"// before\nconfig.setInput(Collections.singletonMap(\"my-input-topic\", null));\n// after\nconfig.setInput(Collections.singletonMap(\"persistent://public/default/my-input-topic\", null));","handlingStrategy":"validation","validationCode":"import org.apache.pulsar.common.naming.TopicName;\nfor (String topic : config.getInput().keySet()) {\n    if (!TopicName.isValid(topic.trim())) {\n        throw new IllegalArgumentException(\"Invalid input topic: \" + topic);\n    }\n}","typeGuard":"boolean isValidPulsarTopic(String t) {\n    return t != null && TopicName.isValid(t.trim());\n}","tryCatchPattern":"try {\n    admin.functions().createFunction(functionConfig, sourceConfigLocation);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Input topic\")) {\n        // inspect config.getInput() topic names and correct fully-qualified form\n    }\n    throw e;\n}","preventionTips":["Always use fully qualified [persistent|non-persistent://]<tenant>/<ns>/<topic> names in function configs","Trim topic strings read from YAML/environment variables","Unit-test generated FunctionConfigs with TopicName.isValid before deployment","Pin tenant/namespace constants in one place to avoid drift"],"tags":["pulsar-functions","validation","topic-name","configuration"],"backgroundTag":"invalid-topic-name","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}