apache/pulsar · error · IllegalArgumentException
No input topic(s) specified for the function
Error message
No input topic(s) specified for the function
What it means
A Pulsar function must consume from at least one input topic; doCommonChecks aggregates all configured inputs (the inputTopics map plus any topicsPattern) via collectAllInputTopics and throws this IllegalArgumentException when the resulting collection is empty.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:808
if (isEmpty(functionConfig.getTenant())) {
throw new IllegalArgumentException("Function tenant cannot be null");
}
if (isEmpty(functionConfig.getNamespace())) {
throw new IllegalArgumentException("Function namespace cannot be null");
}
if (isEmpty(functionConfig.getName())) {
throw new IllegalArgumentException("Function name cannot be null");
}
// go doesn't need className. Java className is done in doJavaChecks.
if (functionConfig.getRuntime() == FunctionConfig.Runtime.PYTHON) {
if (isEmpty(functionConfig.getClassName())) {
throw new IllegalArgumentException("Function classname cannot be null");
}
}
Collection<String> allInputTopics = collectAllInputTopics(functionConfig);
if (allInputTopics.isEmpty()) {
throw new IllegalArgumentException("No input topic(s) specified for the function");
}
for (String topic : allInputTopics) {
if (!TopicName.isValid(topic)) {
throw new IllegalArgumentException(String.format("Input topic %s is invalid", topic));
}
}
if (!isEmpty(functionConfig.getOutput())) {
if (!TopicName.isValid(functionConfig.getOutput())) {
throw new IllegalArgumentException(
String.format("Output topic %s is invalid", functionConfig.getOutput()));
}
}
if (!isEmpty(functionConfig.getLogTopic())) {
if (!TopicName.isValid(functionConfig.getLogTopic())) {
throw new IllegalArgumentException(
String.format("LogTopic topic %s is invalid", functionConfig.getLogTopic()));View on GitHub (pinned to 820761864e)
Solutions
- Add input topics: functionConfig.setInputTopics(Collections.singletonList("persistent://public/default/input-topic")).
- Or use a pattern subscription: functionConfig.setTopicsPattern("persistent://public/default/.*").
- In YAML/JSON configs, add the 'inputs:' (or 'inputSpecs:') entries with correct indentation.
- Verify with pulsar-admin that the topics exist; after this check, each topic must also be a valid TopicName.
Example fix
// before
FunctionConfig config = new FunctionConfig();
config.setTenant("public");
config.setNamespace("default");
// after
FunctionConfig config = new FunctionConfig();
config.setTenant("public");
config.setNamespace("default");
config.setName("my-fn");
config.setInputTopics(Collections.singletonList("persistent://public/default/in-topic")); Defensive patterns
Strategy: validation
Validate before calling
java.util.Collection<String> inputs = FunctionConfigUtils.collectAllInputTopics(config);
if (inputs == null || inputs.isEmpty()) {
throw new IllegalArgumentException("At least one input topic (or topicsPattern) is required");
} Type guard
static boolean hasInputTopics(FunctionConfig c) {
return c != null
&& ((c.getInputSpecs() != null && !c.getInputSpecs().isEmpty())
|| (c.getInputTopics() != null && !c.getInputTopics().isEmpty())
|| (c.getTopicsPattern() != null && !c.getTopicsPattern().trim().isEmpty()));
} Try / catch
try {
FunctionConfigUtils.validateNonJavaFunction(functionConfig, null);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("input topic")) {
throw new IllegalStateException("Configure at least one input topic via 'inputs:' or --inputs", e);
}
throw e;
} Prevention
- Always configure inputs (inputTopics/inputSpecs or topicsPattern) alongside tenant/namespace/name.
- Verify YAML 'inputs:' entries parse into the map — indentation errors silently drop topics.
- Confirm the input topics exist (pulsar-admin topics list) and use fully-qualified persistent:// URLs.
- Run local validation of the assembled FunctionConfig before submitting to the functions worker.
When it happens
Trigger: Submitting a function whose FunctionConfig has neither setInputTopics(...) (or setInputSpecs) nor a topicsPattern, via validateJavaFunction/validateNonJavaFunction, the REST API, or pulsar-admin functions create; a config file missing all 'input' entries.
Common situations: New function configs created from scratch where inputs were deferred; YAML templates with the 'inputs:' section removed or indented wrong so it fails to parse into the map; code refactors renaming input config keys; tests constructing minimal configs without inputs.
Understand the failure class
Background: "X is required", "field cannot be empty", error-the-field-is-required: missing required-field validation errors, explained — this error's family across 39 libraries.
Related errors
- When Guarantees == ATMOST_ONCE, autoAck must be equal to tru
- Function class name is not provided.
- Only one of schemaType or serdeClassName should be set in in
- Only one of outputSchemaType or outputSerdeClassName should
- Function tenant cannot be null
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/255e6ee8a5e8c174.
Report an issue: GitHub.