apache/pulsar · error · IllegalArgumentException

Function namespace cannot be null

Error message

Function namespace cannot be null

What it means

doCommonChecks requires a namespace on the function config; the namespace is the second segment of the fully-qualified function name (tenant/namespace/name). When getNamespace() is null or empty, validation throws this IllegalArgumentException before any submit reaches the functions worker.

Solutions

  1. Call functionConfig.setNamespace("default") (or the intended namespace) before submitting.
  2. Add the missing 'namespace' key to the YAML/JSON config file.
  3. Ensure the namespace exists under the tenant (create it via pulsar-admin namespaces create if needed).
  4. After deserialization, check the value is non-null and non-empty before calling create.

Example fix

// before
config.setTenant("public");
config.setName("my-fn");
// after
config.setTenant("public");
config.setNamespace("default");
config.setName("my-fn");
Defensive patterns

Strategy: validation

Validate before calling

if (config == null || config.getNamespace() == null || config.getNamespace().trim().isEmpty()) {
    throw new IllegalArgumentException("FunctionConfig.namespace must be set before submission");
}

Type guard

static boolean hasNamespace(FunctionConfig c) {
    return c != null && c.getNamespace() != null && !c.getNamespace().trim().isEmpty();
}

Try / catch

try {
    FunctionConfigUtils.validateNonJavaFunction(functionConfig, null);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("namespace")) {
        throw new IllegalStateException("Provide --namespace (e.g. default) when creating the function", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Submitting a function (create/update through FunctionConfigUtils.validateJavaFunction or validateNonJavaFunction, REST API, or pulsar-admin) with a FunctionConfig lacking setNamespace(); YAML/JSON config files missing the 'namespace' key.

Common situations: Programmatic FunctionConfig construction where only tenant and name were set; hand-written YAML templates omitting 'namespace'; migration scripts that changed the config schema and dropped the namespace field.

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/d703c0a48e6ea400. Report an issue: GitHub.

Appendix: source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/FunctionConfigUtils.java:794

        }
    }

    private static void verifyNoTopicClash(Collection<String> inputTopics, String outputTopic)
            throws IllegalArgumentException {
        if (inputTopics.contains(outputTopic)) {
            throw new IllegalArgumentException(
                    String.format(
                            "Output topic %s is also being used as an input topic (topics must be one or the other)",
                            outputTopic));
        }
    }

    public static void doCommonChecks(FunctionConfig functionConfig) {
        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));

View on GitHub (pinned to 820761864e)