{"record":{"id":"58edfef8b47ce3c2","repo":"influxdata/influxdb","slug":"unexpected-err-evaluating-expr-against-batch-e","errorCode":null,"errorMessage":"Unexpected err evaluating {expr:?} against {batch:?}: {e}","messagePattern":"Unexpected err evaluating (.+?) against (.+?): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/predicate/src/rpc_predicate/field_rewrite.rs","lineNumber":173,"sourceCode":"            // 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            })\n            .unwrap();\n\n        assert_eq!(matching.len(), field_names.len());","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/core/predicate/src/rpc_predicate/field_rewrite.rs#L155-L191","documentation":"This is a deliberate panic in test helper code: when evaluating a rewritten DataFusion expression against a RecordBatch, evaluating returned Err, or a scalar result could not be converted to an array. The helper treats any evaluation failure as a hard failure because in this test context every expression is expected to evaluate successfully on the batch.","triggerScenarios":"Calling add_to_predicate (via normalize_predicate or the field_column_rewriter tests) when the rewritten expression's evaluation against the RecordBatch returns Err — e.g. the expression references columns missing from the batch or has a type mismatch after rewriting.","commonSituations":"Adding a new predicate rewrite rule that produces an expression DataFusion cannot evaluate (wrong input types, unresolvable column); changing the batch schema in tests so the rewritten expression no longer matches; upgrading DataFusion so a kernel now errors on previously-valid input.","solutions":["Inspect the wrapped error message for the actual DataFusion evaluation error and the expression/batch dumped in the panic message","Verify the rewritten expression's input columns all exist in the RecordBatch schema with matching types","Check the field-name rewrite mapping so the expression is not left referencing the original (unrewritten) column names","Pin or adapt to the DataFusion version being used, since evaluation kernels can change behavior across releases"],"exampleFix":"// before\nOk(ColumnarValue::Scalar(s)) => s.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| panic!(\"Unexpected err ...: {e}\")),\n// after\nOk(ColumnarValue::Scalar(s)) => s.to_array_of_size(batch.num_rows()).unwrap_or_else(|e| {\n    // debug: ensure expr columns exist in batch before evaluating\n    assert!(expr_columns_in_schema(&expr, batch.schema()), \"expr references missing columns\");\n    panic!(\"eval failure: {e}\")\n}),","handlingStrategy":"try-catch","validationCode":"// Rust: verify expr columns exist in batch before evaluating\nfn expr_columns_in_schema(expr: &Expr, schema: SchemaRef) -> bool {\n    expr.column_refs().iter().all(|c| schema.field_with_name(&c.name).is_ok())\n}","typeGuard":"fn is_ok_result<T>(r: &Result<T, DataFusionError>) -> bool { r.is_ok() }","tryCatchPattern":"match evaluate(&expr, &batch) {\n    Ok(ColumnarValue::Array(a)) => a,\n    Ok(ColumnarValue::Scalar(s)) => s.to_array_of_size(batch.num_rows())? ,\n    Err(e) => { log::error!(\"eval failed for {expr:?}: {e}\"); return Err(e); }\n}","preventionTips":["Always assert expression column refs exist in the batch schema before evaluating","Keep field-name rewrites consistent between expression and batch schema","Pin the DataFusion version in CI and run predicate tests on upgrades","Return typed errors instead of panics in production code paths"],"tags":["rust","datafusion","test-panic","expression-evaluation"],"backgroundTag":"internal-invariant-violation","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"}