risingwavelabs/risingwave · error
unreachable (non-comparator)
Error message
unreachable (non-comparator)
What it means
In get_range's (Some(c), Some(p)) branch where the current value c is less than the previous value p, the code maps the comparator to a decreasing range. Only the four ordering comparators are handled; any other comparator value triggers `unreachable!()`. Like the sibling panics, this indicates the executor was built with an unsupported comparison node type.
Source
Thrown at src/stream/src/executor/dynamic_filter.rs:241
(Some(c), None) | (None, Some(c)) => {
let range = match self.comparator {
GreaterThan => (Excluded(c), Unbounded),
GreaterThanOrEqual => (Included(c), Unbounded),
LessThan => (Unbounded, Excluded(c)),
LessThanOrEqual => (Unbounded, Included(c)),
_ => unreachable!(),
};
let is_insert = curr_is_some;
// The new bound is always towards the last known value
let is_lower = matches!(self.comparator, GreaterThan | GreaterThanOrEqual);
(range, is_lower, is_insert)
}
(Some(c), Some(p)) => {
if c.default_cmp(&p).is_lt() {
let range = match self.comparator {
GreaterThan | LessThanOrEqual => (Excluded(c), Included(p)),
GreaterThanOrEqual | LessThan => (Included(c), Excluded(p)),
_ => unreachable!(),
};
let is_insert = matches!(self.comparator, GreaterThan | GreaterThanOrEqual);
(range, true, is_insert)
} else {
// c > p
let range = match self.comparator {
GreaterThan | LessThanOrEqual => (Excluded(p), Included(c)),
GreaterThanOrEqual | LessThan => (Included(p), Excluded(c)),
_ => unreachable!(),
};
let is_insert = matches!(self.comparator, LessThan | LessThanOrEqual);
(range, false, is_insert)
}
}
(None, None) => unreachable!(), // prev != curr
}
}
View on GitHub (pinned to 6469eb736d)
Solutions
- Confirm the executor construction only ever uses the four ordering comparators (add a debug_assert in new()).
- If a new comparator is intended, extend this match arm and the other two in get_range consistently.
- Log the comparator value before the panic (or convert to an internal error) to make the misconfiguration diagnosable.
Example fix
// before
_ => unreachable!(),
// after
other => return Err(StreamExecutorError::internal(anyhow::anyhow!(
"get_range: unsupported comparator {:?} for decreasing bound", other
))), Defensive patterns
Strategy: validation
Validate before calling
debug_assert!(matches!(self.comparator, GreaterThan | GreaterThanOrEqual | LessThan | LessThanOrEqual), "bad comparator: {:?}", self.comparator); Type guard
fn is_ordering_comparator(c: &PbExprNodeType) -> bool {
matches!(c, PbExprNodeType::GreaterThan | PbExprNodeType::GreaterThanOrEqual | PbExprNodeType::LessThan | PbExprNodeType::LessThanOrEqual)
} Try / catch
let range = match self.comparator {
GreaterThan | LessThanOrEqual => (Excluded(c), Included(p)),
GreaterThanOrEqual | LessThan => (Included(c), Excluded(p)),
other => return Err(StreamExecutorError::internal(anyhow::anyhow!("unsupported comparator {:?}", other))),
}; Prevention
- Keep a single helper that validates the comparator once at construction, not at every match site.
- Add tests covering decreasing right-value transitions for each supported comparator.
- Replace bare unreachable!() with descriptive internal errors during development.
When it happens
Trigger: execute_inner calls get_range when both the previous and current right-side values are non-null and c.default_cmp(&p).is_lt() (the watermark moved backwards / decreased), while self.comparator is not GreaterThan/GreaterThanOrEqual/LessThan/LessThanOrEqual.
Common situations: Encountered during development of new comparator kinds or when a planner bug passes a wrong PbExprNodeType; the decreasing-value branch is hit when the compared column (often an event-time/ingestion timestamp) can regress.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- unreachable (non-comparator or unexpected bound state)
- dynamic filter condition eval must return bool array
- below watermark check condition eval must return bool array
- IcebergSinkWriter should be initialized before barrier
- BatchPosixFsReader should not hit this branch. refer to `bat
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/59eb208370cd1420.
Report an issue: GitHub.