apache/pulsar · error · IllegalArgumentException
Sink tenant cannot be null
Error message
Sink tenant cannot be null
What it means
SinkConfigUtils.validateAndExtractDetails validates a sink configuration before creating/updating a Pulsar IO sink. It throws IllegalArgumentException when the sink's tenant field is null or empty, because tenant is required to build the fully-qualified sink identity (tenant/namespace/name) and to resolve permissions.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:419
sinkConfig.setTransformFunction("builtin://" + functionDetails.getBuiltin());
}
if (!functionDetails.getClassName().equals(IdentityFunction.class.getName())) {
sinkConfig.setTransformFunctionClassName(functionDetails.getClassName());
}
if (!isEmpty(functionDetails.getUserConfig())) {
sinkConfig.setTransformFunctionConfig(functionDetails.getUserConfig());
}
return sinkConfig;
}
public static ExtractedSinkDetails validateAndExtractDetails(SinkConfig sinkConfig,
ValidatableFunctionPackage sinkFunction,
ValidatableFunctionPackage transformFunction,
boolean validateConnectorConfig) {
if (isEmpty(sinkConfig.getTenant())) {
throw new IllegalArgumentException("Sink tenant cannot be null");
}
if (isEmpty(sinkConfig.getNamespace())) {
throw new IllegalArgumentException("Sink namespace cannot be null");
}
if (isEmpty(sinkConfig.getName())) {
throw new IllegalArgumentException("Sink name cannot be null");
}
// make we sure we have one source of input
Collection<String> allInputs = collectAllInputTopics(sinkConfig);
if (allInputs.isEmpty()) {
throw new IllegalArgumentException("Must specify at least one topic of input via topicToSerdeClassName, "
+ "topicsPattern, topicToSchemaType or inputSpecs");
}
for (String topic : allInputs) {
if (!TopicName.isValid(topic)) {
throw new IllegalArgumentException(String.format("Input topic %s is invalid", topic));
}View on GitHub (pinned to 820761864e)
Solutions
- Set tenant on the SinkConfig before submission: sinkConfig.setTenant("public") (or your target tenant).
- Check your config YAML/JSON includes the 'tenant' field under the sink config.
- Verify the code path constructing SinkConfig (e.g. from FunctionConfig conversion) copies tenant correctly.
- Catch IllegalArgumentException and report a clear config error to the user before calling the admin API.
Example fix
// before
SinkConfig cfg = new SinkConfig();
cfg.setNamespace("default");
cfg.setName("my-sink");
// after
SinkConfig cfg = new SinkConfig();
cfg.setTenant("public");
cfg.setNamespace("default");
cfg.setName("my-sink"); Defensive patterns
Strategy: validation
Validate before calling
if (sinkConfig.getTenant() == null || sinkConfig.getTenant().isEmpty()) {
throw new IllegalArgumentException("sinkConfig.tenant must be set before submission");
} Type guard
static boolean hasTenant(SinkConfig cfg) {
return cfg != null && cfg.getTenant() != null && !cfg.getTenant().trim().isEmpty();
} Try / catch
try {
SinkConfigUtils.validateAndExtractDetails(cfg, sinkPkg, transformPkg, true);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("tenant")) {
log.error("Sink config missing tenant: fix config and retry", e);
}
throw e;
} Prevention
- Always set tenant (namespace, name) together when building a SinkConfig.
- Load configs through a schema-validated YAML parser that marks tenant required.
- Reuse a shared builder that enforces the required identity triple.
- Add a unit test asserting the fully-qualified name tenant/namespace/name is complete.
When it happens
Trigger: Calling createSink/updateSink (or the sink create REST/admin API, or pulsar-admin sink create) with a SinkConfig whose setTenant() was never called or was set to empty string.
Common situations: Programmatically building SinkConfig from YAML/JSON where the tenant key was misspelled or omitted; deserialization from a partial config file; frameworks generating configs that skip tenant.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Sink namespace cannot be null
- Sink name cannot be null
- Must specify at least one topic of input via topicToSerdeCla
- ResourceGroupCreate: Invalid null ResourceGroup config
- ResourceGroupCreate: can't create resource group with an emp
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/db08954d546164f1.
Report an issue: GitHub.