{"record":{"id":"ad932e6e81b083ce","repo":"apache/pulsar","slug":"label-name-cannot-be-null-or-empty","errorCode":null,"errorMessage":"Label name cannot be null or empty","messagePattern":"Label name cannot be null or empty","errorType":"http","errorClass":"org.apache.pulsar.broker.admin.RestException","httpStatus":400,"severity":"error","filePath":"pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java","lineNumber":2552,"sourceCode":"        return healthChecker;\n    }\n\n    // https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels\n    public void validateCustomMetricLabelKeys(Set<String> allowedCustomMetricLabelKeys) {\n        if (allowedCustomMetricLabelKeys == null) {\n            return;\n        }\n        boolean exposeCustomTopicMetricLabelsEnabled = config.isExposeCustomTopicMetricLabelsEnabled();\n        if (exposeCustomTopicMetricLabelsEnabled) {\n            for (String labelKey : allowedCustomMetricLabelKeys) {\n                isValidMetricsName(labelKey);\n            }\n        }\n    }\n\n    private static void isValidMetricsName(String labelName) {\n        if (labelName == null || labelName.isEmpty()) {\n            throw new RestException(Response.Status.BAD_REQUEST, \"Label name cannot be null or empty\");\n        }\n\n        // Prometheus reserves all labels starting with \"__\" for internal use.\n        if (labelName.startsWith(\"__\")) {\n            throw new RestException(Response.Status.BAD_REQUEST,\n                    String.format(\"Label name '%s' is invalid: Prometheus reserves all labels starting with '__' \"\n                            + \"for internal use\", labelName));\n        }\n\n        // Pulsar reserves all labels starting with \"pulsar_\" or \"pulsar.\" for internal use.\n        if (labelName.endsWith(\"pulsar.\") || labelName.endsWith(\"pulsar_\")) {\n            throw new RestException(Response.Status.BAD_REQUEST,\n                    String.format(\"Label name '%s' is invalid: Pulsar reserves all labels starting with 'pulsar_' \"\n                            + \"or 'pulsar.' for internal use\", labelName));\n        }\n\n        // OpenTelemetry reserves all labels starting with \"otel_\" or \"otel.\" for internal use.\n        if (labelName.startsWith(\"otel.\") || labelName.startsWith(\"otel_\")) {","sourceCodeStart":2534,"sourceCodeEnd":2570,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java#L2534-L2570","documentation":"isValidMetricsName validates a user-supplied Prometheus metrics label name before it is registered. A null or empty label name cannot form a valid label, so the broker rejects the request with HTTP 400. This guard exists because Prometheus label names must be non-empty and must not collide with reserved prefixes.","triggerScenarios":"Registering or updating broker metrics with an additional label whose name is null or an empty string, e.g. via the metrics admin endpoint or code that passes an unset label name into PulsarService.isValidMetricsName.","commonSituations":"A metrics configuration entry with a missing name key; programmatic metric registration where the label name variable is uninitialized; YAML/JSON config where the label name field was omitted.","solutions":["Supply a non-empty label name that matches [a-zA-Z_][a-zA-Z0-9_]*.","Check the metrics/label configuration source (broker.conf, YAML, JSON) for missing or blank name fields.","Add caller-side validation to reject null/blank label names before sending them to the broker."],"exampleFix":"// before\nString labelName = config.get(\"label\"); // may be null\nbroker.metricsRegister(\"my_metric\", labelName, value);\n\n// after\nString labelName = config.get(\"label\");\nif (labelName == null || labelName.isEmpty()) {\n    throw new IllegalArgumentException(\"metrics label name is required\");\n}\nbroker.metricsRegister(\"my_metric\", labelName, value);","handlingStrategy":"validation","validationCode":"void requireValidLabelName(String name) {\n    if (name == null || name.isEmpty()) throw new IllegalArgumentException(\"label name required\");\n    if (!name.matches(\"[a-zA-Z_][a-zA-Z0-9_]*\")) throw new IllegalArgumentException(\"invalid label name: \" + name);\n}","typeGuard":"boolean isValidLabelName(String name) {\n    return name != null && name.matches(\"[a-zA-Z_][a-zA-Z0-9_]*\");\n}","tryCatchPattern":"try {\n    metricsApi.registerLabel(labelName);\n} catch (RestException e) {\n    if (e.getResponse().getStatus() == 400) {\n        log.error(\"Rejected label name '{}': fix and resubmit\", labelName);\n    }\n}","preventionTips":["Validate label names with the Prometheus regex before any metrics registration","Never derive label names from unparsed config keys that may be missing or blank","Keep a shared constant/util for label-name validation across your metrics tooling"],"tags":["metrics","prometheus","validation","rest"],"backgroundTag":"metrics-label-name-invalid","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"}