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

  1. Verify all field_predicates are boolean comparison expressions over the _field column; strip or reject non-boolean exprs before evaluation
  2. Check DataFusion version compatibility between predicate crates — Scalar::to_array_of_size behavior changed across versions
  3. Inspect the expr and batch printed in the panic message to spot the type mismatch
  4. 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

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


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)