risingwavelabs/risingwave · error

cannot find subscription with id

Error message

cannot find subscription with id {}

What it means

get_subscription_by_id looks up subscription catalog objects by id, maps them to PbSubscription models, and uses find_or_first(|_| true) to select the match. When the filtered iterator is empty (no subscription row/object exists for the given id), the ok_or_else on the resulting Option produces this anyhow error. It simply means no subscription with the requested id exists in the catalog.

Solutions

  1. Verify the subscription id via the catalog (SHOW SUBSCRIPTIONS) before fetching by id.
  2. Handle the not-found case: recreate the subscription if it was dropped.
  3. Use the subscription name lookup instead of a cached id.

Example fix

// before
let sub = controller.get_subscription_by_id(stale_id).await?;
// after
match controller.get_subscription_by_id(id).await {
    Ok(sub) => sub,
    Err(e) if e.to_string().contains("cannot find subscription") => recreate_subscription(),
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust
async fn subscription_exists(controller: &CatalogController, id: u32) -> bool {
    controller.list_subscriptions().await.map(|subs| subs.iter().any(|s| s.id == id)).unwrap_or(false)
}

Try / catch

match controller.get_subscription_by_id(id).await {
    Ok(sub) => sub,
    Err(e) if e.to_string().contains("cannot find subscription with id") => {
        // treat as RecordNotFound: refresh catalog or recreate
        refresh_and_recreate(id)
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling get_subscription_by_id (e.g. via SHOW/META internal RPC) with a subscription_id that does not exist, or one that was already dropped in another session/transaction.

Common situations: Consumers holding stale subscription ids after the subscription was dropped; racing DDL where a subscription is removed while a client queries it; typos or id reuse assumptions in tooling.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at src/meta/src/controller/catalog/get_op.rs:342

            })
            .collect())
    }

    pub async fn get_subscription_by_id(
        &self,
        subscription_id: SubscriptionId,
    ) -> MetaResult<PbSubscription> {
        let inner = self.inner.read().await;
        let subscription_objs = Subscription::find()
            .find_also_related(Object)
            .filter(subscription::Column::SubscriptionId.eq(subscription_id))
            .all(&inner.db)
            .await?;
        let subscription: PbSubscription = subscription_objs
            .into_iter()
            .map(|(subscription, obj)| ObjectModel(subscription, obj.unwrap(), None).into())
            .find_or_first(|_| true)
            .ok_or_else(|| anyhow!("cannot find subscription with id {}", subscription_id))?;

        Ok(subscription)
    }

    pub async fn get_mv_depended_subscriptions(
        &self,
        database_id: Option<DatabaseId>,
    ) -> MetaResult<HashMap<TableId, HashMap<SubscriptionId, u64>>> {
        let inner = self.inner.read().await;
        let select = Subscription::find()
            .select_only()
            .select_column(subscription::Column::SubscriptionId)
            .select_column(subscription::Column::DependentTableId)
            .select_column(subscription::Column::RetentionSeconds);
        let select = if let Some(database_id) = database_id {
            select
                .join(JoinType::InnerJoin, subscription::Relation::Object.def())
                .filter(object::Column::DatabaseId.eq(database_id))

View on GitHub (pinned to 6469eb736d)