apache/pulsar · error · IllegalArgumentException
Sink namespace cannot be null
Error message
Sink namespace cannot be null
What it means
validateAndExtractDetails throws IllegalArgumentException when the SinkConfig namespace field is null or empty. Tenant, namespace, and name together form the unique sink identity, so namespace must be present.
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java:422
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));
}
}
if (!isEmpty(sinkConfig.getLogTopic())) {
if (!TopicName.isValid(sinkConfig.getLogTopic())) {View on GitHub (pinned to 820761864e)
Solutions
- Call sinkConfig.setNamespace("default") before submission.
- Add the 'namespace' key to your sink YAML/JSON config.
- If deriving from FunctionConfig, ensure namespace is copied over.
- Validate tenant/namespace/name triple client-side before calling the admin API.
Example fix
// before
sinkConfig.setTenant("public");
// after
sinkConfig.setTenant("public");
sinkConfig.setNamespace("default"); Defensive patterns
Strategy: validation
Validate before calling
if (sinkConfig.getNamespace() == null || sinkConfig.getNamespace().isEmpty()) {
throw new IllegalArgumentException("sinkConfig.namespace must be set before submission");
} Type guard
static boolean hasNamespace(SinkConfig cfg) {
return cfg != null && cfg.getNamespace() != null && !cfg.getNamespace().trim().isEmpty();
} Try / catch
try {
SinkConfigUtils.validateAndExtractDetails(cfg, sinkPkg, transformPkg, true);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("namespace")) {
log.error("Sink config missing namespace: fix config and retry", e);
}
throw e;
} Prevention
- Default to namespace 'default' if your tooling has no explicit namespace.
- Validate tenant/namespace/name as a group before submission.
- Keep namespace names lowercase-alphanumeric to avoid downstream validation failures.
- Test config-file parsing against a sample with all required fields.
When it happens
Trigger: Submitting a SinkConfig with tenant set but getNamespace() empty — e.g. sink created via admin API or SinkConfigUtils without setNamespace().
Common situations: Copy-pasted config templates missing 'namespace'; tenant-scoped tools that set tenant but forget namespace; migrations from older configs.
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 tenant 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/8bd0c58a202a85f5.
Report an issue: GitHub.