{"record":{"id":"394ab79cfdfe3723","repo":"apache/pulsar","slug":"sink-name-is-not-provided","errorCode":null,"errorMessage":"Sink name is not provided","messagePattern":"Sink name is not provided","errorType":"http","errorClass":"RestException","httpStatus":400,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java","lineNumber":97,"sourceCode":"                             final String sinkName,\n                             final InputStream uploadedInputStream,\n                             final FormDataContentDisposition fileDetail,\n                             final String sinkPkgUrl,\n                             final SinkConfig sinkConfig,\n                             final AuthenticationParameters authParams) {\n\n        if (!isWorkerServiceAvailable()) {\n            throwUnavailableException();\n        }\n\n        if (tenant == null) {\n            throw new RestException(Response.Status.BAD_REQUEST, \"Tenant is not provided\");\n        }\n        if (namespace == null) {\n            throw new RestException(Response.Status.BAD_REQUEST, \"Namespace is not provided\");\n        }\n        if (sinkName == null) {\n            throw new RestException(Response.Status.BAD_REQUEST, \"Sink name is not provided\");\n        }\n        if (sinkConfig == null) {\n            throw new RestException(Response.Status.BAD_REQUEST, \"Sink config is not provided\");\n        }\n\n        throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, sinkName, \"register\", authParams);\n\n        try {\n            // Check tenant exists\n            worker().getBrokerAdmin().tenants().getTenantInfo(tenant);\n\n            String qualifiedNamespace = tenant + \"/\" + namespace;\n            List<String> namespaces = worker().getBrokerAdmin().namespaces().getNamespaces(tenant);\n            if (namespaces != null && !namespaces.contains(qualifiedNamespace)) {\n                String qualifiedNamespaceWithCluster = String.format(\"%s/%s/%s\", tenant,\n                        worker().getWorkerConfig().getPulsarFunctionsCluster(), namespace);\n                if (namespaces != null && !namespaces.contains(qualifiedNamespaceWithCluster)) {\n                    log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", sinkName)","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/SinksImpl.java#L79-L115","documentation":"registerSink in SinksImpl throws a 400 Bad Request RestException when sinkName is null. The sink name is the identity of the component within tenant/namespace, required to build the function metadata record. This is the third in the chain of mandatory-parameter checks, evaluated after tenant and namespace.","triggerScenarios":"Calling the sink registration endpoint with sinkName=null: omitted sinkName path segment, null argument to SinksImpl.registerSink, or a name that was never set in the SinkConfig and not passed separately.","commonSituations":"CLI tools deriving the name from a file name that is empty; SDK calls that expect the name to come from SinkConfig but pass null explicitly; copy-pasted request code where the name placeholder was never filled.","solutions":["Provide the sinkName path segment in the REST URL and/or pass a non-null name to registerSink.","If the name should come from SinkConfig, set sinkConfig.setName(...) before submitting and pass that config.","Validate all of tenant/namespace/sinkName client-side before calling the API to get one clean error."],"exampleFix":"// before\nsinks.registerSink(tenant, namespace, null, sinkConfig, ...);\n// after\nString name = sinkConfig.getName();\nif (name == null || name.isBlank()) {\n    throw new IllegalArgumentException(\"sink name is required\");\n}\nsinks.registerSink(tenant, namespace, name, sinkConfig, ...);","handlingStrategy":"validation","validationCode":"String name = sinkConfig != null ? sinkConfig.getName() : null;\nif (name == null || name.isBlank()) {\n    throw new IllegalArgumentException(\"sink name must be provided\");\n}","typeGuard":"boolean hasSinkName(String sinkName) {\n    return sinkName != null && !sinkName.isBlank();\n}","tryCatchPattern":"try {\n    sinks.registerSink(tenant, ns, name, cfg, null, null, null, authParams);\n} catch (RestException e) {\n    if (e.getResponse().getStatus() == 400 && \"Sink name is not provided\".equals(e.getMessage())) {\n        // derive the name from config or CLI args and retry\n    } else { throw e; }\n}","preventionTips":["Set the name in SinkConfig and pass it explicitly rather than relying on defaults","Validate tenant/namespace/name together before any REST call","Make CLI tools fail on empty derived names instead of sending null"],"tags":["rest-api","bad-request","validation","pulsar-sinks"],"backgroundTag":"missing-required-parameter","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"}