risingwavelabs/risingwave · error
upsert stream is not supported as input of {}, plan: {}
Error message
upsert stream is not supported as input of {}, plan:
{} What it means
This macro checks the stream kind of an operator's input during optimization. RisingWave cannot build certain stream operators (e.g. aggregations, joins that require append-only or non-upsert input) on top of an upsert stream, so it bails with the operator name and the full plan text.
Source
Thrown at src/frontend/src/optimizer/property/stream_kind.rs:123
}
}
/// Reject upsert stream as input.
macro_rules! reject_upsert_input {
($input:expr) => {
reject_upsert_input!(
$input,
std::any::type_name::<Self>().split("::").last().unwrap()
)
};
($input:expr, $curr:expr) => {{
use crate::optimizer::plan_node::Explain;
use crate::optimizer::property::StreamKind;
let kind = $input.stream_kind();
if let StreamKind::Upsert = kind {
risingwave_common::bail!(
"upsert stream is not supported as input of {}, plan:\n{}",
$curr,
$input.explain_to_string()
);
}
kind
}};
}
pub(crate) use reject_upsert_input;
View on GitHub (pinned to 6469eb736d)
Solutions
- Rewrite the query to consume the upsert stream through an operator that supports upsert input (e.g. use an aggregation or a supported sink).
- Define the upstream MV without upsert (use an append-only source or add a primary key that makes it append-compatible).
- Read the embedded plan text to identify which node produces the upsert kind and restructure above it.
- Upgrade or restructure per current docs on supported upsert input operators.
Example fix
-- before: plain count over an upsert MV CREATE MATERIALIZED VIEW mv2 AS SELECT count(*) FROM upsert_mv; -- after: force retraction-aware aggregation or use append-only input CREATE MATERIALIZED VIEW mv2 AS SELECT count(*) FROM (SELECT * FROM upsert_mv) GROUP BY 1; -- or build on append-only source
Defensive patterns
Strategy: validation
Validate before calling
// Before creating an MV over a stream, verify it is not upsert -- SELECT ... check upstream MV definition; append-only sources only
Try / catch
// Wrap MV creation and read the bail message's plan text to find the upsert node CREATE MATERIALIZED VIEW ...; -- on failure, inspect plan text in the error for 'Upsert'
Prevention
- Only build new MVs on append-only sources or non-upsert upstream MVs
- Check upstream MV stream kind in docs before composing operators
- Add a primary key to sources to keep streams append-only where possible
When it happens
Trigger: Optimizer applying a plan-node macro (`assert...` style) whose macro receives an input whose `stream_kind()` is `StreamKind::Upsert`; typically when a user query composes an operator above an upsert-producing source or MV.
Common situations: Creating an MV or query on top of an upsert materialized view/source with operators that lack upsert input support; version changes that tighten stream-kind requirements.
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
- should always have a stream key in the stream plan but not,
- update should always be converted to batch plan
- If you want to use upsert, please set the keysType of doris
- next offset {:?} should be later than current offset {:?}
- new item epoch {} does not match current chunk offset epoch
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/a9a2ab03dfbadc3d.
Report an issue: GitHub.