influxdata/influxdb · error
Unexpected err converting scalar result from evaluating
Error message
Unexpected err converting scalar result from evaluating {expr:?} against {batch:?}: {e} What it means
After evaluating field predicates against the synthesized `_field` record batch, a Scalar result must be converted to an array of batch.num_rows(); `unwrap_or_else(|e| panic!(...))` aborts if DataFusion's scalar-to-array conversion fails (e.g. scalar type/length mismatch with the batch schema). A companion panic covers outright evaluation errors. This is an internal inconsistency between the expr's result type and the constructed batch.
Solutions
- Verify all field_predicates are boolean comparison expressions over the _field column; strip or reject non-boolean exprs before evaluation
- Check DataFusion version compatibility between predicate crates — Scalar::to_array_of_size behavior changed across versions
- Inspect the expr and batch printed in the panic message to spot the type mismatch
- Replace the panic with error propagation (map evaluate errors into DataFusionError) for library callers
Example fix
// before
s.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| {
panic!("Unexpected err converting scalar result ...: {e}")
})
// after
s.to_array_of_size(batch.num_rows())
.map_err(|e| DataFusionError::Internal(format!("scalar to array failed for {expr:?}: {e}")))? Defensive patterns
Strategy: validation
Validate before calling
// caller-side: ensure predicates evaluate to Boolean over the _field column
fn is_boolean_field_cmp(expr: &Expr, field_col: &str) -> bool {
matches!(expr, Expr::BinaryExpr(b) if b.is_comparison_operator()
&& expr_supports_column(b, field_col))
} Try / catch
// panic (panic!/unwrap_or_else) — validate inputs rather than catching;
// if you must isolate it:
let result = std::panic::catch_unwind(|| rewriter.add_to_predicate(expr.clone()));
if result.is_err() { /* fall back to unrewritten predicate */ } Prevention
- Keep all field predicates boolean-valued comparison expressions
- Match the DataFusion version used across all predicate crates
- Read the expr/batch dump in the panic message to identify type mismatches quickly
- Replace panics with propagated DataFusionError in library paths
When it happens
Trigger: add_to_predicate evaluates an expr whose scalar result cannot be converted to an array of the batch's row count — typically a type mismatch between the predicate expr's output type (non-boolean, e.g. dictionary/string) and expectations, or a corrupted batch schema.
Common situations: Field predicates producing non-scalarizable values; DataFusion version changes altering ColumnarValue::Scalar conversion; mixing comparison ops whose result types diverge from Boolean.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- at least one expr
- Error creating _field record batch
- expected bucket id, got string
- expected bucket id, got TS range
- expected datatime column value but got
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/a60e5967c1df528b.
Report an issue: GitHub.
Appendix: source
Thrown at core/predicate/src/rpc_predicate/field_rewrite.rs:170
let matching = exprs
.into_iter()
// evaluate each field_predicate against the actual field
// names. For example, if we have two predicates like
//
// _field !~= 'f2'
// _field != 'f3'
//
// We will produce two output arrays:
// ┌─────────┐ ┌─────────┐
// │ true │ │ true │
// │ false │ │ true │
// │ true │ │ false │
// └─────────┘ └─────────┘
.map(|expr| match expr.evaluate(&batch) {
Ok(ColumnarValue::Array(arr)) => arr,
Ok(ColumnarValue::Scalar(s)) => {
s.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| {
panic!("Unexpected err converting scalar result from evaluating {expr:?} against {batch:?}: {e}")
})
}
Err(e) => panic!("Unexpected err evaluating {expr:?} against {batch:?}: {e}"),
})
// Now combine the arrays using AND to get a single output
// boolean array. For the example above, we would get
// ┌─────────┐
// │ true │
// │ false │
// │ false │
// └─────────┘
.reduce(|acc, arr| {
// apply boolean AND
let bool_array =
kernels::boolean::and(as_boolean_array(&acc), as_boolean_array(&arr))
.expect("Error computing AND");
Arc::new(bool_array) as ArrayRef
})View on GitHub (pinned to 06200ef96b)