risingwavelabs/risingwave · error

truncate offset earlier than prev truncate offset

Error message

truncate offset {:?} earlier than prev truncate offset {:?}

What it means

Guard in the KV log store reader's truncate: the requested truncate offset is earlier than (or equal to) the previously truncated offset. Truncation must be monotonically increasing; a backward truncate request is a caller bug and is rejected.

Solutions

  1. Inspect the offset bookkeeping: a truncate request is below the previously applied truncate offset, indicating out-of-order or duplicate truncation.
  2. Check the upstream barrier/truncate sequencing; restart the fragment so the log store reader re-initializes its offsets.
  3. If reproducible, report as a bug with the job and offsets from the message.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at src/stream/src/common/log_store_impl/kv_log_store/reader.rs:529 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at src/stream/src/common/log_store_impl/kv_log_store/reader.rs:529

                    },
                )
            }
        })
    }

    fn truncate(&mut self, offset: TruncateOffset) -> LogStoreResult<()> {
        if offset > self.latest_offset.expect("should exist before truncation") {
            return Err(anyhow!(
                "truncate at a later offset {:?} than the current latest offset {:?}",
                offset,
                self.latest_offset
            ));
        }
        if offset.epoch() >= self.first_write_epoch.expect("should have init") {
            if let Some(truncate_offset) = &self.truncate_offset
                && offset <= *truncate_offset
            {
                return Err(anyhow!(
                    "truncate offset {:?} earlier than prev truncate offset {:?}",
                    offset,
                    truncate_offset
                ));
            }
            self.rx.truncate_buffer(offset);
            self.truncate_offset = Some(offset);
        } else {
            // For historical data, no need to truncate at seq id level. Only truncate at barrier.
            if let TruncateOffset::Barrier { epoch } = &offset {
                if let Some(truncate_offset) = &self.truncate_offset
                    && offset <= *truncate_offset
                {
                    return Err(anyhow!(
                        "truncate offset {:?} earlier than prev truncate offset {:?}",
                        offset,
                        truncate_offset
                    ));

View on GitHub (pinned to 6469eb736d)