risingwavelabs/risingwave · error

invalid partition index number

Error message

invalid partition index number

What it means

Guard in Topic::sub_topic: rejects a negative partition index when constructing a partitioned Pulsar topic. Partition indexes must be non-negative; a negative value would produce an invalid topic name like `topic-partition-(-1)`, so the call fails instead.

Source

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

impl Topic {
    pub fn is_partitioned_topic(&self) -> bool {
        self.partition_index.is_none()
    }

    pub fn rest_path(&self) -> String {
        format!(
            "{}/{}/{}/{}",
            self.domain,
            self.tenant,
            self.namespace,
            encode(&self.topic)
        )
    }

    pub fn sub_topic(&self, partition: i32) -> Result<Topic> {
        if partition < 0 {
            bail!("invalid partition index number");
        }

        if self.topic.contains(PARTITIONED_TOPIC_SUFFIX) {
            return Ok(self.clone());
        }

        Ok(Topic {
            domain: self.domain.clone(),
            tenant: self.tenant.clone(),
            namespace: self.namespace.clone(),
            topic: format!("{}{}{}", self.topic, PARTITIONED_TOPIC_SUFFIX, partition),
            partition_index: Some(partition),
        })
    }

    pub fn topic_str_without_partition(&self) -> Result<String> {
        if self.topic.contains(PARTITIONED_TOPIC_SUFFIX) {
            let parts: Vec<&str> = self.topic.split(PARTITIONED_TOPIC_SUFFIX).collect();

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Pass a valid partition index >= 0; guard the call site for the non-partitioned case instead of using -1.
  2. If the topic is non-partitioned, skip sub_topic entirely — topics already containing '-partition-' suffix are returned unchanged.
  3. Fix upstream code that initializes partition numbers to -1.

Example fix

// before
let topic = topic.sub_topic(partition)?; // partition = -1
// after
let topic = if partition >= 0 { topic.sub_topic(partition)? } else { topic.clone() };
Defensive patterns

Strategy: type-guard

Validate before calling

if partition < 0 {
    return Err("partition index must be >= 0".into());
}

Type guard

fn valid_partition(p: i32) -> Option<u32> {
    u32::try_from(p).ok()
}

Try / catch

match topic.sub_topic(partition) {
    Err(_) if partition < 0 => Ok(topic.clone()), // non-partitioned sentinel case
    other => other,
}

Prevention

When it happens

Trigger: Calling sub_topic with a negative partition value, typically a -1 sentinel meaning 'no partition' passed where an actual partition index (>= 0) is required.

Common situations: Using -1 as a default/uninitialized partition value and passing it to sub_topic; off-by-one loop bounds producing a negative index; non-partitioned topics where partition info is absent.

Related errors


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