influxdata/influxdb · error
at least one expr
Error message
at least one expr
What it means
`rewrite_field_exprs` uses `.reduce(|acc, expr| acc.and(expr)).expect("at least one expr")`, which panics if the iterator of rewritten conjuncts is empty. The iterator comes from splitting the predicate into conjuncts, so it panics only when a predicate yields zero conjuncts (e.g. an empty/`Literal(true)`-stripped expression).
Solutions
- Guard the caller: skip rewriting (or short-circuit to true) when the predicate is empty or has no conjuncts
- Inspect how the predicate was parsed — an empty predicate should not reach rewrite_field_exprs
- Fix the conjunct-splitting function so a literal-true predicate yields at least one expr
- Replace the expect with reduce_initial or a fallback returning Transformed::no(orig_expr)
Example fix
// before
.reduce(|acc, expr| acc.and(expr))
.expect("at least one expr");
// after
match conjuncts {
[] => Transformed::no(orig_expr),
[one] => Transformed::yes(one.clone()),
many => Transformed::yes(many.iter().cloned().fold(Expr::Literal(true), |a, e| a.and(e))),
} Defensive patterns
Strategy: validation
Validate before calling
// caller-side guard before normalize_predicate
if predicate.expr() == &Expr::Literal(ScalarValue::Boolean(Some(true))) || predicate_is_empty(&predicate) {
return Ok(predicate); // nothing to rewrite
} Try / catch
// this is a panic (expect), not a catchable error; guard instead
// wrap calls during diagnosis:
let result = std::panic::catch_unwind(|| rewriter.rewrite(expr.clone()));
match result { Ok(t) => t, Err(_) => /* fall back to original expr */ } Prevention
- Skip rewriting for empty or literal-true predicates
- Make the conjunct-splitting function always return at least one expr
- Prefer reduce with an initial value (fold) over reduce+expect
- Add unit tests for degenerate predicates (empty, literal true/false)
When it happens
Trigger: Calling normalize_predicate / FieldColumnRewriter with a predicate expression whose conjunct list is empty after splitting — e.g. a predicate that is just `TRUE`/empty, or upstream splitting producing Vec::new().
Common situations: Passing default/empty predicates through the field-rewrite path; upstream changes to conjunction splitting that now emit zero exprs; InfluxQL/SQL translation producing degenerate predicates.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Error creating _field record batch
- Unexpected err converting scalar result from evaluating
- Unexpected content in ValueExpr
- auto field family exists
- Azure blob storage support not enabled, recompile with the…
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/0152777fa0e474a3.
Report an issue: GitHub.
Appendix: source
Thrown at core/predicate/src/rpc_predicate/field_rewrite.rs:76
/// Rewrites the predicate. See the description on
/// [`FieldProjectionRewriter`] for more details.
pub(crate) fn rewrite_field_exprs(
&mut self,
expr: Expr,
) -> DataFusionResult<Transformed<Expr>> {
// for predicates like `A AND B AND C`
// rewrite `A`, `B` and `C` separately and put them back together
let rewritten_expr = split_conjunction_owned(expr)
.into_iter()
// apply the rewrite individually
.map(|expr| self.rewrite_single_conjunct(expr))
// check for errors
.collect::<DataFusionResult<Vec<Expr>>>()?
// put the Exprs back together with AND
.into_iter()
.reduce(|acc, expr| acc.and(expr))
.expect("at least one expr");
Ok(Transformed::yes(rewritten_expr))
}
// Rewrites a single predicate. Does not handle AND specially
fn rewrite_single_conjunct(&mut self, expr: Expr) -> DataFusionResult<Expr> {
let mut finder = ColumnReferencesFinder::default();
expr.visit(&mut finder)?;
// rewrite any expression that only references _field to `true`
match (finder.saw_field_reference, finder.saw_non_field_reference) {
// Only saw _field column references, rewrite
(true, false) => {
self.field_predicates.push(expr);
Ok(lit(true))
}
// saw both _field and other column references, can't handle this case yet
// https://github.com/influxdata/influxdb_iox/issues/5310View on GitHub (pinned to 06200ef96b)