risingwavelabs/risingwave · error
batch refresh materialized views must not depend on sources
Error message
batch refresh materialized views must not depend on sources directly; fragment {} has source/source-backfill nodes What it means
Batch refresh materialized views must not read from sources directly. The meta node scans each fragment's FragmentTypeFlag and, if any fragment contains Source or SourceScan nodes, it bails, because split assignment resolution is skipped for batch refresh jobs and direct source reads would be left unresolved.
Source
Thrown at src/meta/src/stream/stream_manager.rs:685
};
let job_type = if let Some(refresh_interval_sec) = refresh_interval_sec {
if since_timestamp_epoch.is_some() {
bail!("since_timestamp should not be specified when no snapshot backfill");
}
let snapshot_backfill_info = snapshot_backfill_info.ok_or_else(|| {
anyhow::anyhow!(
"batch refresh materialized view must have snapshot backfill upstream"
)
})?;
// Batch refresh jobs must not contain source or source-backfill nodes,
// because we skip split assignment resolution for them.
for fragment in info.stream_job_fragments.inner.fragments.values() {
let mask = fragment.fragment_type_mask;
if mask.contains(FragmentTypeFlag::Source)
|| mask.contains(FragmentTypeFlag::SourceScan)
{
bail!(
"batch refresh materialized views must not depend on sources directly; \
fragment {} has source/source-backfill nodes",
fragment.fragment_id
);
}
}
tracing::debug!(
?snapshot_backfill_info,
refresh_interval_sec,
"sending Command::CreateBatchRefreshStreamingJob"
);
CreateStreamingJobType::BatchRefresh(BatchRefreshInfo {
snapshot_backfill_info,
refresh_interval_sec,
})
} else if let Some(snapshot_backfill_info) = snapshot_backfill_info {
tracing::debug!(
?snapshot_backfill_info,View on GitHub (pinned to 6469eb736d)
Solutions
- Insert an intermediate regular (non-batch-refresh) MV between the source and the batch refresh MV, then build the refresh MV on top of that MV.
- Replace the direct source read with a table/MV as the upstream of the batch refresh job.
- If reading the source directly is required, use a normal streaming MV instead of batch refresh.
Example fix
// before CREATE MATERIALIZED VIEW mv WITH (refresh = '10 minutes') AS SELECT * FROM src; // after CREATE MATERIALIZED VIEW base_mv AS SELECT * FROM src; CREATE MATERIALIZED VIEW mv WITH (refresh = '10 minutes') AS SELECT * FROM base_mv;
Defensive patterns
Strategy: validation
Validate before calling
-- ensure the batch refresh MV does not read a source directly -- build on MVs/tables only: CREATE MATERIALIZED VIEW base_mv AS SELECT * FROM src; CREATE MATERIALIZED VIEW mv WITH (refresh = '10 minutes') AS SELECT * FROM base_mv;
Try / catch
match result {
Err(e) if e.to_string().contains("must not depend on sources directly") =>
return Err("insert an intermediate MV between the source and the batch refresh MV".into()),
other => other,
} Prevention
- Never put a source directly in the FROM chain of a batch refresh MV.
- Keep an architecture rule: sources -> regular MVs -> batch refresh MVs.
- Review fragment type masks in EXPLAIN/fragment graphs when designing refresh pipelines.
When it happens
Trigger: Creating a batch refresh MV (refresh_interval_sec set, snapshot_backfill_info present) whose plan contains a fragment with fragment_type_mask containing FragmentTypeFlag::Source or SourceScan — i.e. the MV reads a source (or a source-backfill node) directly in its dependency chain.
Common situations: `CREATE MATERIALIZED VIEW ... WITH (refresh=...) AS SELECT ... FROM <source>`; building a refresh MV on top of a chain of MVs where one still reads a source directly; users migrating pipelines that previously used regular streaming MVs on sources.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Table or source '{}' specified in backfill_order is not used
- Time travel is not supported for the source
- since_timestamp should not be specified when no snapshot bac
- batch refresh materialized view must have snapshot backfill
- additional column type {} is not supported for connector {},
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/a4ce92abd7f6acc4.
Report an issue: GitHub.