apache/pulsar · error · IllegalArgumentException

Cannot derive a tenant/namespace from --regex pattern '${pat

Error message

Cannot derive a tenant/namespace from --regex pattern '${pattern}'. Use a fully-qualified pattern, e.g. persistent://tenant/namespace/.*

What it means

namespaceFromPattern derives the tenant/namespace to look up topics from a --regex subscription pattern by stripping the scheme and taking the first two path segments. If the pattern does not contain at least tenant/namespace after the scheme, an IllegalArgumentException is thrown because the CLI cannot determine which namespace to list topics in.

Source

Thrown at pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdConsume.java:284

                                     java.util.function.Consumer<String> namespaceFn) {
        if (isRegex) {
            namespaceFn.accept(namespaceFromPattern(topic));
        } else {
            topicFn.accept(topic);
        }
    }

    static String namespaceFromPattern(String pattern) {
        // Strip an optional persistent:// / non-persistent:// domain prefix, then take the first
        // two path segments as tenant/namespace.
        String rest = pattern;
        int scheme = rest.indexOf("://");
        if (scheme >= 0) {
            rest = rest.substring(scheme + 3);
        }
        String[] parts = rest.split("/");
        if (parts.length < 2) {
            throw new IllegalArgumentException("Cannot derive a tenant/namespace from --regex pattern '"
                    + pattern + "'. Use a fully-qualified pattern, e.g. persistent://tenant/namespace/.*");
        }
        return parts[0] + "/" + parts[1];
    }

    private ConsumerEncryptionPolicy buildConsumerEncryptionPolicy() {
        return buildFileDecryptionPolicy(this.encKeyValue, cryptoFailureAction);
    }

    @VisibleForTesting
    public String getWebSocketConsumeUri(String topic) {
        String serviceURLWithoutTrailingSlash = serviceURL.substring(0,
                serviceURL.endsWith("/") ? serviceURL.length() - 1 : serviceURL.length());

        TopicName topicName = TopicName.get(topic);
        String wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(),
                topicName.getNamespacePortion(), topicName.getLocalName());

View on GitHub (pinned to 820761864e)

Solutions

  1. Use a fully-qualified pattern: --regex 'persistent://my-tenant/my-ns/.*'
  2. Keep at least tenant/namespace in the pattern before the wildcard portion, e.g. persistent://public/default/my-topic-.*
  3. If you truly need cross-namespace discovery, run the CLI once per namespace pattern

Example fix

// before
--regex 'orders-.*'
// after
--regex 'persistent://public/default/orders-.*'
Defensive patterns

Strategy: validation

Validate before calling

String rest = pattern.replaceAll("^[a-z]+://", "");
String[] parts = rest.split("/");
if (parts.length < 2 || parts[0].isEmpty() || parts[1].isEmpty())
    throw new IllegalArgumentException("--regex must be fully qualified: persistent://tenant/namespace/...");

Type guard

static boolean isFullyQualifiedTopicPattern(String p) {
    String rest = p.contains("://") ? p.substring(p.indexOf("://") + 3) : p;
    String[] parts = rest.split("/");
    return parts.length >= 2 && !parts[0].isEmpty() && !parts[1].isEmpty();
}

Try / catch

try {
    String ns = namespaceFromPattern(pattern);
} catch (IllegalArgumentException e) {
    LOG.error("{} — defaulting pattern prefix to persistent://public/default/", e.getMessage());
    pattern = "persistent://public/default/" + pattern.replaceFirst("^[a-z]+://", "");
}

Prevention

When it happens

Trigger: Passing a --regex like '.*', 'mytopic-.*', or 'topic://x' — anything that after removing 'scheme://' yields fewer than 2 slash-separated segments when applyTopicSelection calls namespaceFromPattern.

Common situations: Writing a regex meant to match topics across all namespaces; shortening persistent://tenant/ns/topic.* to just topic.*; confusing --regex (needs fully-qualified pattern) with plain topic-name matching.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/eff8de90f70ed338. Report an issue: GitHub.