apache/pulsar · error · org.apache.pulsar.broker.admin.RestException
Label name '%s' is invalid: must match the regex [a-zA-Z_][a
Error message
Label name '%s' is invalid: must match the regex [a-zA-Z_][a-zA-Z0-9_]*
What it means
Prometheus label names must match the pattern [a-zA-Z_][a-zA-Z0-9_]* — start with a letter or underscore and contain only letters, digits, and underscores. Pulsar enforces this via METRICS_LABEL_NAME_PATTERN in isValidMetricsName and rejects non-conforming names with HTTP 400.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java:2578
}
// Pulsar reserves all labels starting with "pulsar_" or "pulsar." for internal use.
if (labelName.endsWith("pulsar.") || labelName.endsWith("pulsar_")) {
throw new RestException(Response.Status.BAD_REQUEST,
String.format("Label name '%s' is invalid: Pulsar reserves all labels starting with 'pulsar_' "
+ "or 'pulsar.' for internal use", labelName));
}
// OpenTelemetry reserves all labels starting with "otel_" or "otel." for internal use.
if (labelName.startsWith("otel.") || labelName.startsWith("otel_")) {
throw new RestException(Response.Status.BAD_REQUEST,
String.format("Label name '%s' is invalid: OpenTelemetry reserves all labels starting with "
+ "'otel_' or 'otel.' for internal use", labelName));
}
boolean matches = METRICS_LABEL_NAME_PATTERN.matcher(labelName).matches();
if (!matches) {
throw new RestException(Response.Status.BAD_REQUEST,
String.format("Label name '%s' is invalid: must match the regex [a-zA-Z_][a-zA-Z0-9_]*", labelName));
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Sanitize the label name to match [a-zA-Z_][a-zA-Z0-9_]*: replace invalid characters with underscores and ensure it starts with a letter or underscore.
- Move problematic characters (dots, slashes) into the label VALUE instead of the name.
- Add a client-side regex check before calling the broker to fail fast with a clearer message.
Example fix
// before
metrics.registerLabel("my-label.name");
// after
String safe = label.replaceAll("[^a-zA-Z0-9_]", "_");
if (!safe.matches("[a-zA-Z_][a-zA-Z0-9_]*")) {
safe = "_" + safe;
}
metrics.registerLabel(safe); Defensive patterns
Strategy: validation
Validate before calling
boolean isValidPrometheusName(String s) {
return s != null && s.matches("[a-zA-Z_][a-zA-Z0-9_]*");
} Type guard
String toSafeLabelName(String raw) {
if (raw == null) return null;
String s = raw.replaceAll("[^a-zA-Z0-9_]", "_");
return s.isEmpty() || Character.isDigit(s.charAt(0)) ? "_" + s : s;
} Try / catch
try {
metricsApi.registerLabel(labelName);
} catch (RestException e) {
if (e.getResponse().getStatus() == 400) {
metricsApi.registerLabel(toSafeLabelName(labelName));
}
} Prevention
- Run every label name through the [a-zA-Z_][a-zA-Z0-9_]* regex before sending
- Convert dots/hyphens in source names (JMX, hostnames) to underscores
- Put high-cardinality detail in label values, not names
When it happens
Trigger: Registering a metrics label containing invalid characters such as hyphens, dots, spaces, or starting with a digit (e.g. "my-label", "my.label", "1label") via the broker metrics API.
Common situations: Using metric/label names copied from systems allowing dots or dashes (e.g. JMX or StatsD names); programmatically generating labels from hostnames or topic names containing dots and slashes; config files with human-readable label names.
Related errors
- Label name cannot be null or empty
- Label name '%s' is invalid: Prometheus reserves all labels s
- Label name '%s' is invalid: Pulsar reserves all labels start
- Label name '%s' is invalid: OpenTelemetry reserves all label
- Cannot derive a tenant/namespace from --regex pattern '${pat
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/bb2e49ebaa9097f5.
Report an issue: GitHub.