{"record":{"id":"34b26f37d0eb462d","repo":"apache/pulsar","slug":"sink-name-cannot-be-null","errorCode":null,"errorMessage":"Sink name cannot be null","messagePattern":"Sink name 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":425,"sourceCode":"            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())) {\n                throw new IllegalArgumentException(\n                        String.format(\"LogTopic topic %s is invalid\", sinkConfig.getLogTopic()));\n            }","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/SinkConfigUtils.java#L407-L443","documentation":"Config validation entry point in SinkConfigUtils.validateAndExtractDetails: the sink configuration is missing a required field — the excerpt shows the first check firing on an empty tenant (with sink name null-ness among the guards) — so the sink cannot be registered; the incomplete SinkConfig field is the faulty input.","triggerScenarios":"Creating a sink where SinkConfig.setName() was never invoked, e.g. pulsar-admin sink create without --name and no name in the config file.","commonSituations":"CLI usage relying on the archive to provide a name; generated configs omitting 'name'; test harnesses building minimal configs.","solutions":["Set the sink name in the config"],"exampleFix":"// before\nSinkConfig cfg = new SinkConfig();\ncfg.setTenant(\"public\");\ncfg.setNamespace(\"default\");\n// after\nSinkConfig cfg = new SinkConfig();\ncfg.setTenant(\"public\");\ncfg.setNamespace(\"default\");\ncfg.setName(\"elastic-sink\");","handlingStrategy":"validation","validationCode":"if (sinkConfig.getName() == null || sinkConfig.getName().isEmpty()) {\n    throw new IllegalArgumentException(\"sinkConfig.name must be set before submission\");\n}","typeGuard":"static boolean hasName(SinkConfig cfg) {\n    return cfg != null && cfg.getName() != null && !cfg.getName().trim().isEmpty();\n}","tryCatchPattern":"try {\n    SinkConfigUtils.validateAndExtractDetails(cfg, sinkPkg, transformPkg, true);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"name\")) {\n        log.error(\"Sink config missing name: fix config and retry\", e);\n    }\n    throw e;\n}","preventionTips":["Always provide the sink name explicitly rather than relying on CLI defaults.","Generate names deterministically in tooling that creates many sinks.","Include name in config-file templates with a non-empty placeholder.","Validate tenant, namespace, and name together before submission."],"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-14T00:17:10.932Z"}