{"record":{"id":"a60e5967c1df528b","repo":"influxdata/influxdb","slug":"unexpected-err-converting-scalar-result-from-evaluating-expr","errorCode":null,"errorMessage":"Unexpected err converting scalar result from evaluating {expr:?} against {batch:?}: {e}","messagePattern":"Unexpected err converting scalar result from evaluating (.+?) against (.+?): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/predicate/src/rpc_predicate/field_rewrite.rs","lineNumber":170,"sourceCode":"        let matching = exprs\n            .into_iter()\n            // evaluate each field_predicate against the actual field\n            // names. For example, if we have two predicates like\n            //\n            // _field !~= 'f2'\n            // _field != 'f3'\n            //\n            // We will produce two output arrays:\n            // ┌─────────┐  ┌─────────┐\n            // │  true   │  │  true   │\n            // │  false  │  │  true   │\n            // │  true   │  │  false  │\n            // └─────────┘  └─────────┘\n            .map(|expr| match expr.evaluate(&batch) {\n                Ok(ColumnarValue::Array(arr)) => arr,\n                Ok(ColumnarValue::Scalar(s)) => {\n                    s.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| {\n                        panic!(\"Unexpected err converting scalar result from evaluating {expr:?} against {batch:?}: {e}\")\n                    })\n                }\n                Err(e) => panic!(\"Unexpected err evaluating {expr:?} against {batch:?}: {e}\"),\n            })\n            // Now combine the arrays using AND to get a single output\n            // boolean array. For the example above, we would get\n            // ┌─────────┐\n            // │  true   │\n            // │  false  │\n            // │  false  │\n            // └─────────┘\n            .reduce(|acc, arr| {\n                // apply boolean AND\n                let bool_array =\n                    kernels::boolean::and(as_boolean_array(&acc), as_boolean_array(&arr))\n                        .expect(\"Error computing AND\");\n                Arc::new(bool_array) as ArrayRef\n            })","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/core/predicate/src/rpc_predicate/field_rewrite.rs#L152-L188","documentation":"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.","triggerScenarios":"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.","commonSituations":"Field predicates producing non-scalarizable values; DataFusion version changes altering ColumnarValue::Scalar conversion; mixing comparison ops whose result types diverge from Boolean.","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"],"exampleFix":"// before\ns.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| {\n    panic!(\"Unexpected err converting scalar result ...: {e}\")\n})\n// after\ns.to_array_of_size(batch.num_rows())\n    .map_err(|e| DataFusionError::Internal(format!(\"scalar to array failed for {expr:?}: {e}\")))?","handlingStrategy":"validation","validationCode":"// caller-side: ensure predicates evaluate to Boolean over the _field column\nfn is_boolean_field_cmp(expr: &Expr, field_col: &str) -> bool {\n    matches!(expr, Expr::BinaryExpr(b) if b.is_comparison_operator()\n        && expr_supports_column(b, field_col))\n}","typeGuard":null,"tryCatchPattern":"// panic (panic!/unwrap_or_else) — validate inputs rather than catching;\n// if you must isolate it:\nlet result = std::panic::catch_unwind(|| rewriter.add_to_predicate(expr.clone()));\nif result.is_err() { /* fall back to unrewritten predicate */ }","preventionTips":["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"],"tags":["panic","datafusion","type-mismatch","predicate"],"backgroundTag":"type-mismatch","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}