risingwavelabs/risingwave · error
Backfill order strategy has a cycle
Error message
Backfill order strategy has a cycle
What it means
The user-supplied backfill_order pairs are turned into a directed graph over scanned relation ids; plan_fixed_strategy runs has_cycle on the resulting order. A cycle (e.g. A->B, B->A) makes a total backfill ordering impossible, so creation is rejected.
Source
Thrown at src/frontend/src/optimizer/backfill_order_strategy.rs:341
start_name
);
};
let Some(end_scanned_relation_ids) = scanned_relation_ids.get(&end_relation_id) else {
bail!(
"Table or source '{}' specified in backfill_order is not used in the query",
end_name
);
};
for start_scanned_relation_id in start_scanned_relation_ids {
order
.entry(*start_scanned_relation_id)
.or_default()
.extend(end_scanned_relation_ids.iter().copied());
}
}
if has_cycle(&order) {
bail!("Backfill order strategy has a cycle");
}
Ok(order)
}
}
mod common {
use std::collections::{HashMap, HashSet};
use risingwave_pb::id::RelationId;
use risingwave_sqlparser::ast::ObjectName;
use crate::Binder;
use crate::catalog::CatalogError;
use crate::catalog::root_catalog::SchemaPath;
use crate::catalog::schema_catalog::SchemaCatalog;
use crate::error::Result;
use crate::session::SessionImpl;
View on GitHub (pinned to 6469eb736d)
Solutions
- Draw the dependency graph implied by your pairs and remove the contradictory edge(s).
- Delete duplicate/redundant pairs that imply both directions between two tables.
- Ensure the order is a strict topological order of the query's relations.
- Omit backfill_order and let RisingWave choose an order if no strict ordering is needed.
Example fix
// before WITH (backfill_order = 'a -> b, b -> a') // after WITH (backfill_order = 'a -> b')
Defensive patterns
Strategy: validation
Validate before calling
-- pairs must form a DAG; check for both-direction pairs before DDL -- bad: backfill_order = 'a -> b, b -> a'
Try / catch
match create_mv_result {
Err(e) if e.to_string().contains("has a cycle") => {
eprintln!("backfill_order edges form a cycle; remove contradictory pairs");
}
other => other?,
} Prevention
- Sketch the ordering as a diagram and confirm it is acyclic before writing DDL.
- Never emit both 'a -> b' and 'b -> a'.
- Validate ordering clauses in CI with a small script that checks for cycles.
When it happens
Trigger: Specifying backfill_order pairs whose dependency edges form a loop, such as 'a -> b' together with 'b -> a', directly or transitively across multiple pairs.
Common situations: Conflicting ordering statements across several pairs, misunderstanding the arrow direction (pairs are not symmetric), or copy-pasting orders that contradict each other.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Table or source '{}' specified in backfill_order is not used
- Invalid order key: empty item in `{expr}`
- Invalid order key item `{item}`
- Invalid order key item `{item}` HINT: Supported format is `c
- Invalid order key column `{column}` HINT: Only plain column
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/17dd88867291130a.
Report an issue: GitHub.