risingwavelabs/risingwave · error

subscription on table {} has invalid retention seconds {}

Error message

subscription on table {} has invalid retention seconds {}

What it means

get_table_change_log_truncate_info reads subscription retention_seconds, stored as i64, from the subscription catalog and converts each to u64. A negative or overflowing value cannot convert, producing this error naming the table and raw value.

Source

Thrown at src/meta/src/controller/streaming_job.rs:259

impl CatalogController {
    pub async fn get_table_change_log_truncate_info(
        &self,
    ) -> MetaResult<TableChangeLogTruncateInfo> {
        let inner = self.inner.read().await;

        let subscriptions: Vec<(TableId, i64)> = Subscription::find()
            .select_only()
            .columns([
                subscription::Column::DependentTableId,
                subscription::Column::RetentionSeconds,
            ])
            .into_tuple()
            .all(&inner.db)
            .await?;
        let mut subscription_retention_seconds = HashMap::new();
        for (table_id, retention_seconds) in subscriptions {
            let retention_seconds = u64::try_from(retention_seconds).map_err(|_| {
                anyhow!(
                    "subscription on table {} has invalid retention seconds {}",
                    table_id,
                    retention_seconds
                )
            })?;
            subscription_retention_seconds
                .entry(table_id)
                .and_modify(|retention: &mut u64| *retention = (*retention).max(retention_seconds))
                .or_insert(retention_seconds);
        }

        let jobs: Vec<JobId> = StreamingJobModel::find()
            .select_only()
            .column(streaming_job::Column::JobId)
            .filter(
                Condition::any()
                    .add(streaming_job::Column::JobStatus.eq(JobStatus::Creating))
                    .add(streaming_job::Column::RefreshIntervalSec.is_not_null()),

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Query the subscription table for the listed table_id and correct the negative retention_seconds to a valid non-negative value.
  2. Drop and re-create the subscription with a valid retention setting if the row is corrupted.
  3. Check whether any code path writes -1 or i64 sentinel values as retention and fix the writer.
  4. Restart the meta node after repair so truncate info computation retries.

Example fix

// before
-- catalog row: retention_seconds = -1
UPDATE subscription SET retention_seconds = 86400 WHERE dependent_table_id = <table_id>;
// after
-- or via SQL: drop and recreate with valid retention
DROP SUBSCRIPTION sub;
CREATE SUBSCRIPTION sub FROM mv WITH (retention_seconds = 86400);
Defensive patterns

Strategy: validation

Validate before calling

SELECT dependent_table_id, retention_seconds FROM subscription WHERE retention_seconds < 0;
-- must return zero rows before triggering truncate-info computation

Type guard

fn valid_retention(v: i64) -> Option<u64> { u64::try_from(v).ok() }

Try / catch

match u64::try_from(retention_seconds) {
    Ok(v) => map.insert(table_id, v),
    Err(_) => {
        warn!("skipping subscription on table {table_id}: invalid retention {retention_seconds}");
        // repair the row before re-running truncate info
    }
}

Prevention

When it happens

Trigger: Any subscription row whose retention_seconds is negative or exceeds u64::MAX — e.g. a corrupted or manually edited catalog value, a sentinel like i64::MIN/-1 written by a buggy code path, or deserialized protobuf defaults written as -1.

Common situations: Manual SQL fixes on the catalog; a version where -1 encoded 'infinite retention' before the format changed; interrupted CREATE SUBSCRIPTION writing a partial value.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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