risingwavelabs/risingwave · error · anyhow::Error
plan "{}" does not have a valid fragment id
Error message
plan "{}" does not have a valid fragment id What it means
In parse_plan (risectl reschedule), each semicolon-separated segment must match the regex `<fragment_id>:[<worker deltas>]`; if the fragment part cannot be captured, the input plan string is malformed and this error is returned. The input at fault is the `plan` argument that does not follow the `1:[1:+1,2:-1]` format.
Source
Thrown at src/ctl/src/cmd_impl/meta/reschedule.rs:159
// It will match formats like `1:[1:+1,2:-1,3:1];2:[1:1,2:1]`, indicating which workers' actors need to change in quantity for each fragment.
fn parse_plan(mut plan: String) -> Result<HashMap<u32, PbWorkerReschedule>> {
let mut reschedules = HashMap::new();
let regex = Regex::new(r"^(\d+):\[((?:\d+:[+-]?\d+,?)+)]$")?;
plan.retain(|c| !c.is_whitespace());
for fragment_reschedule_plan in plan.split(';') {
if fragment_reschedule_plan.is_empty() {
continue;
}
let captures = regex
.captures(fragment_reschedule_plan)
.ok_or_else(|| anyhow!("plan \"{}\" format illegal", fragment_reschedule_plan))?;
let fragment_id = captures
.get(1)
.and_then(|mat| mat.as_str().parse::<u32>().ok())
.ok_or_else(|| anyhow!("plan \"{}\" does not have a valid fragment id", plan))?;
let worker_changes: Vec<&str> = captures[2].split(',').collect();
let mut worker_actor_diff = HashMap::new();
for worker_change in &worker_changes {
let (worker_id, count) = worker_change.split(':').collect_tuple::<(_, _)>().unwrap();
let worker_id = worker_id.parse().unwrap();
let count = count.parse().unwrap();
if let Some(dup_change) = worker_actor_diff.insert(worker_id, count) {
anyhow::bail!(
"duplicate worker id {worker_id} in plan, prev {worker_id} -> {dup_change}",
);
}
}
if !worker_actor_diff.is_empty() {
reschedules.insert(fragment_id, PbWorkerReschedule { worker_actor_diff });View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure each plan section starts with a valid numeric fragment id
- Use the correct fragment ids from the meta catalog, not job or worker ids
- Regenerate the plan from the cluster rather than editing ids by hand
Defensive patterns
Strategy: validation
Validate before calling
if !fragment_id_str.chars().all(|c| c.is_ascii_digit()) || fragment_id_str.is_empty() {
return Err(anyhow!("fragment id must be numeric"));
} Prevention
- Verify fragment ids from the meta catalog
- Do not substitute table or worker ids for fragment ids
When it happens
Trigger: A plan section whose first captured group is non-numeric or absent (e.g. 'abc [1:3]' or an empty fragment id).
Common situations: Corrupted or hand-modified plan text; using a table/job id where a fragment id is expected.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- plan "{}" format illegal
- Invalid time: {value} {unit} is out of range for a time of d
- Can't cast string to date (expected format is YYYY-MM-DD)
- Can't cast string to time (expected format is HH:MM:SS[.D+{u
- Can't cast string to timestamp (expected format is YYYY-MM-D
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/38e745aa35ff2192.
Report an issue: GitHub.