risingwavelabs/risingwave · error

streaming vector index lookup join only support append-only…

Error message

streaming vector index lookup join only support append-only input

What it means

The vector index lookup join executor reads from the append-only vector source's snapshot-read side and cannot process updates or deletes: any chunk containing an op other than `Op::Insert` aborts with this error. Vector index structures assume append-only input for correctness of lookups.

Solutions

  1. Use only INSERT (append-only) workloads on the vector source table; recreate rows instead of updating them.
  2. Declare/check the source as append-only so writes violating it are rejected at ingest time.
  3. If mutations are required, drop and rebuild the vector index/table from an append-only re-ingestion.

Example fix

-- before
UPDATE embeddings SET vec = new_vec WHERE id = 1;
-- after
INSERT INTO embeddings (id, vec) VALUES (1, new_vec); -- append-only model
Defensive patterns

Strategy: validation

Validate before calling

-- ensure the source is append-only before creating a vector index lookup join
-- reject UPDATE/DELETE on the vector table in your application layer

Prevention

When it happens

Trigger: A chunk with `UpdateDelete`, `UpdateInsert`, or `Delete` ops arrives at the lookup-join read side during `execute_inner`, e.g. the upstream vector table receives UPDATE or DELETE statements while a vector index lookup join is consuming it.

Common situations: Running `UPDATE`/`DELETE` (or `UPDATE` via upsert semantics) on the embedding table feeding a vector index; CDC sources that emit update/delete events; users assuming the vector table is mutable like a normal table.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/stream/src/executor/vector/index_lookup_join.rs:82

            .new_snapshot(HummockReadEpoch::Committed(first_epoch.prev))
            .await?;

        while let Some(msg) = input.try_next().await? {
            match msg {
                Message::Barrier(barrier) => {
                    let is_checkpoint = barrier.is_checkpoint();
                    let prev_epoch = barrier.epoch.prev;
                    yield Message::Barrier(barrier);
                    if is_checkpoint {
                        read_snapshot = reader
                            .new_snapshot(HummockReadEpoch::Committed(prev_epoch))
                            .await?;
                    }
                }
                Message::Chunk(chunk) => {
                    let (chunk, ops) = chunk.into_parts();
                    if ops.iter().any(|op| *op != Op::Insert) {
                        bail!("streaming vector index lookup join only support append-only input");
                    }
                    let chunk = read_snapshot
                        .query_expand_chunk(chunk, vector_column_idx)
                        .await?;
                    yield Message::Chunk(StreamChunk::from_parts(ops, chunk));
                }
                Message::Watermark(watermark) => {
                    yield Message::Watermark(watermark);
                }
            }
        }
    }
}

View on GitHub (pinned to 6469eb736d)