apache/pulsar · error · IllegalArgumentException

Source tenant cannot be null

Error message

Source tenant cannot be null

What it means

SourceConfigUtils.validateAndExtractDetails validates a Pulsar IO Source configuration before creating/registering a source connector. The 'tenant' field is mandatory because every source must live inside a tenant/namespace/name fully-qualified function identity. The library throws IllegalArgumentException immediately when tenant is null or empty rather than producing a partially-constructed source.

Source

Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SourceConfigUtils.java:266

            sourceConfig.setResources(resources);
        }

        if (!isEmpty(functionDetails.getRuntimeFlags())) {
            sourceConfig.setRuntimeFlags(functionDetails.getRuntimeFlags());
        }

        if (!isEmpty(functionDetails.getCustomRuntimeOptions())) {
            sourceConfig.setCustomRuntimeOptions(functionDetails.getCustomRuntimeOptions());
        }

        return sourceConfig;
    }

    public static ExtractedSourceDetails validateAndExtractDetails(SourceConfig sourceConfig,
                                                                   ValidatableFunctionPackage sourceFunction,
                                                                   boolean validateConnectorConfig) {
        if (isEmpty(sourceConfig.getTenant())) {
            throw new IllegalArgumentException("Source tenant cannot be null");
        }
        if (isEmpty(sourceConfig.getNamespace())) {
            throw new IllegalArgumentException("Source namespace cannot be null");
        }
        if (isEmpty(sourceConfig.getName())) {
            throw new IllegalArgumentException("Source name cannot be null");
        }
        if (!isEmpty(sourceConfig.getTopicName()) && !TopicName.isValid(sourceConfig.getTopicName())) {
            throw new IllegalArgumentException("Topic name is invalid");
        }
        if (!isEmpty(sourceConfig.getLogTopic())) {
            if (!TopicName.isValid(sourceConfig.getLogTopic())) {
                throw new IllegalArgumentException(
                        String.format("LogTopic topic %s is invalid", sourceConfig.getLogTopic()));
            }
        }
        if (sourceConfig.getParallelism() != null && sourceConfig.getParallelism() <= 0) {
            throw new IllegalArgumentException("Source parallelism must be a positive number");

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the tenant on the SourceConfig before validation, e.g. sourceConfig.setTenant("public") or the tenant you intend to use
  2. If the tenant should come from user input (CLI flag / REST field), check it is present and reject the request with a clear 400 message before calling validateAndExtractDetails
  3. If loading from a config file, add 'tenant' to the YAML/JSON and re-load the SourceConfig

Example fix

// before
SourceConfig cfg = new SourceConfig();
cfg.setNamespace("default");
cfg.setName("my-source");
// after
SourceConfig cfg = new SourceConfig();
cfg.setTenant("public");
cfg.setNamespace("default");
cfg.setName("my-source");
Defensive patterns

Strategy: validation

Validate before calling

if (sourceConfig == null || sourceConfig.getTenant() == null || sourceConfig.getTenant().isEmpty()) {
    throw new IllegalArgumentException("sourceConfig.tenant must be set before validation");
}

Type guard

static boolean hasTenant(SourceConfig cfg) {
    return cfg != null && cfg.getTenant() != null && !cfg.getTenant().trim().isEmpty();
}

Try / catch

try {
    SourceConfigUtils.validateAndExtractDetails(cfg, pkg, true);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Source tenant cannot be null")) {
        // surface a 400-style message asking the user to supply --tenant
    }
}

Prevention

When it happens

Trigger: Calling validateAndExtractDetails (directly or via source registration APIs like SourcesBase.create/update or the CLI 'pulsar-admin sources create') with a SourceConfig whose tenant field is null or an empty string.

Common situations: Building SourceConfig programmatically and forgetting setTenant(); deserializing a JSON/YAML source config file that lacks a 'tenant' key; copying a config template and deleting the tenant line; wiring configs through layers where tenant is filled in later than validation runs.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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