{"record":{"id":"8bd0c58a202a85f5","repo":"apache/pulsar","slug":"sink-namespace-cannot-be-null","errorCode":null,"errorMessage":"Sink namespace cannot be null","messagePattern":"Sink namespace cannot be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java","lineNumber":422,"sourceCode":"            sinkConfig.setTransformFunctionClassName(functionDetails.getClassName());\n        }\n        if (!isEmpty(functionDetails.getUserConfig())) {\n            sinkConfig.setTransformFunctionConfig(functionDetails.getUserConfig());\n        }\n\n\n        return sinkConfig;\n    }\n\n    public static ExtractedSinkDetails validateAndExtractDetails(SinkConfig sinkConfig,\n                                                                 ValidatableFunctionPackage sinkFunction,\n                                                                 ValidatableFunctionPackage transformFunction,\n                                                                 boolean validateConnectorConfig) {\n        if (isEmpty(sinkConfig.getTenant())) {\n            throw new IllegalArgumentException(\"Sink tenant cannot be null\");\n        }\n        if (isEmpty(sinkConfig.getNamespace())) {\n            throw new IllegalArgumentException(\"Sink namespace cannot be null\");\n        }\n        if (isEmpty(sinkConfig.getName())) {\n            throw new IllegalArgumentException(\"Sink name cannot be null\");\n        }\n\n        // make we sure we have one source of input\n        Collection<String> allInputs = collectAllInputTopics(sinkConfig);\n        if (allInputs.isEmpty()) {\n            throw new IllegalArgumentException(\"Must specify at least one topic of input via topicToSerdeClassName, \"\n                    + \"topicsPattern, topicToSchemaType or inputSpecs\");\n        }\n        for (String topic : allInputs) {\n            if (!TopicName.isValid(topic)) {\n                throw new IllegalArgumentException(String.format(\"Input topic %s is invalid\", topic));\n            }\n        }\n        if (!isEmpty(sinkConfig.getLogTopic())) {\n            if (!TopicName.isValid(sinkConfig.getLogTopic())) {","sourceCodeStart":404,"sourceCodeEnd":440,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java#L404-L440","documentation":"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.","triggerScenarios":"Submitting a SinkConfig with tenant set but getNamespace() empty — e.g. sink created via admin API or SinkConfigUtils without setNamespace().","commonSituations":"Copy-pasted config templates missing 'namespace'; tenant-scoped tools that set tenant but forget namespace; migrations from older configs.","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."],"exampleFix":"// before\nsinkConfig.setTenant(\"public\");\n// after\nsinkConfig.setTenant(\"public\");\nsinkConfig.setNamespace(\"default\");","handlingStrategy":"validation","validationCode":"if (sinkConfig.getNamespace() == null || sinkConfig.getNamespace().isEmpty()) {\n    throw new IllegalArgumentException(\"sinkConfig.namespace must be set before submission\");\n}","typeGuard":"static boolean hasNamespace(SinkConfig cfg) {\n    return cfg != null && cfg.getNamespace() != null && !cfg.getNamespace().trim().isEmpty();\n}","tryCatchPattern":"try {\n    SinkConfigUtils.validateAndExtractDetails(cfg, sinkPkg, transformPkg, true);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"namespace\")) {\n        log.error(\"Sink config missing namespace: fix config and retry\", e);\n    }\n    throw e;\n}","preventionTips":["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."],"tags":["pulsar","config-validation","sink","illegal-argument"],"backgroundTag":"missing-required-field","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}