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

  1. Add input topics: functionConfig.setInputTopics(Collections.singletonList("persistent://public/default/input-topic")).
  2. Or use a pattern subscription: functionConfig.setTopicsPattern("persistent://public/default/.*").
  3. In YAML/JSON configs, add the 'inputs:' (or 'inputSpecs:') entries with correct indentation.
  4. 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

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


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