risingwavelabs/risingwave · error

The domain only can be specified as 'persistent' or 'non-per

Error message

The domain only can be specified as 'persistent' or 'non-persistent'. Input domain is '{}'

What it means

Pulsar topic URLs must begin with the 'persistent://' or 'non-persistent://' domain. parse_topic splits the input on '://' and rejects any topic whose scheme is neither, because RisingWave needs the domain to construct the fully-qualified Pulsar topic path used by the connector.

Source

Thrown at src/connector/src/source/pulsar/topic.rs:142

                PERSISTENT_DOMAIN, PUBLIC_TENANT, DEFAULT_NAMESPACE, parts[0],
            ),
            3 => format!("{}://{}", PERSISTENT_DOMAIN, topic),
            _ => {
                bail!(
                    "Invalid short topic name '{}', \
                it should be in the format of <tenant>/<namespace>/<topic> or <topic>",
                    topic
                );
            }
        };
    }

    let parts: Vec<&str> = complete_topic.splitn(2, "://").collect();

    let domain = match parts[0] {
        PERSISTENT_DOMAIN | NON_PERSISTENT_DOMAIN => parts[0],
        _ => {
            bail!(
                "The domain only can be specified as 'persistent' or 'non-persistent'. Input domain is '{}'",
                parts[0]
            );
        }
    };

    let rest = parts[1];
    let parts: Vec<&str> = rest.splitn(3, '/').collect();

    if parts.len() != 3 {
        bail!(
            "invalid topic name '{}'; it must be in the format <tenant>/<namespace>/<topic>",
            rest
        );
    }

    let parsed_topic = Topic {
        domain: domain.to_owned(),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Fix the domain prefix to exactly 'persistent://' or 'non-persistent://'
  2. If no domain is intended, pass the topic as 'tenant/namespace/topic' (3 slash-separated parts) or a bare topic name so it is auto-prefixed
  3. Check for typos like 'persistant' or trailing whitespace before '://'

Example fix

// before
let topic = parse_topic("persistant://public/default/events");
// after
let topic = parse_topic("persistent://public/default/events");
Defensive patterns

Strategy: validation

Validate before calling

function validatePulsarDomain(topic) {
  if (topic.includes('://') && !/^(persistent|non-persistent):\/\//.test(topic)) {
    throw new Error(`domain must be 'persistent' or 'non-persistent': ${topic}`);
  }
}

Type guard

const hasValidPulsarDomain = (t) => !t.includes('://') || /^(persistent|non-persistent):\/\//.test(t);

Try / catch

try { const topic = parse_topic(input); } catch (e) { if (String(e).includes("domain only can be specified")) { fixDomainAndRetry(); } else { throw e; } }

Prevention

When it happens

Trigger: Calling Topic::new/parse_topic with a topic string whose scheme (the part before '://') is misspelled or unrecognized, e.g. 'persistant://tenant/ns/topic', 'kafka://...', or a bare URL with an unknown prefix.

Common situations: Copy-pasting a topic URI from another messaging system, typos in 'persistent'/'non-persistent', or users omitting a '/' so the auto-defaulting branch (which prepends persistent://public/default/) does not apply.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/c1c406f35094ec3e. Report an issue: GitHub.