influxdata/influxdb · error
Expected scalar value
Error message
Expected scalar value
What it means
Panic in the scalar_value_passthrough test of date_bin_wallclock: the date_bin wallclock UDF is documented/expected to return a ColumnarValue::Scalar when given scalar inputs, so any other variant (ColumnarValue::Array) is a contract violation and the test panics.
Solutions
- Ensure the UDF's invoke has a scalar fast-path that returns ColumnarValue::Scalar when all inputs are scalars
- Check the interval argument is a ScalarValue and not accidentally converted to an array upstream
- Compare against the DataFusion version's ColumnarValue semantics for scalar UDFs
- If behavior is intentionally array-only, update the test expectation rather than the function
Example fix
// before (UDF invoke)
ColumnarValue::Array(...) // always array
// after
if args.iter().all(|a| matches!(a, ColumnarValue::Scalar(_))) {
ColumnarValue::Scalar(ScalarValue::TimestampNanosecond(Some(binned), tz.clone()))
} else {
ColumnarValue::Array(...)
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust: verify UDF returns scalar for scalar-only args before unwrapping
fn returns_scalar(v: &ColumnarValue) -> bool { matches!(v, ColumnarValue::Scalar(_)) } Type guard
fn expect_scalar(v: ColumnarValue) -> Option<ScalarValue> {
match v { ColumnarValue::Scalar(s) => Some(s), _ => None }
} Try / catch
let scalar = match result {
ColumnarValue::Scalar(s) => s,
other => panic!("Expected scalar value, got: {other:?}"),
}; Prevention
- Keep a scalar fast-path in UDF invoke implementations
- Test both scalar and array invocation modes of each UDF
- Match ColumnarValue exhaustively rather than assuming a variant
- Check DataFusion release notes for ScalarUDF/ColumnarValue semantic changes
When it happens
Trigger: Calling date_bin_wallclock's invoke with scalar timestamp and interval arguments and receiving ColumnarValue::Array instead of ColumnarValue::Scalar — i.e. the function implementation stopped special-casing scalar inputs.
Common situations: Refactoring the UDF's invoke to always return arrays; a DataFusion ScalarUDF trait version change altering how scalar-only calls are represented; forgetting the scalar fast-path after adding timezone support.
Related errors
- Error computing AND
- Unexpected err evaluating
- datafusion error
- error while executing plan
- Expected array value
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/daa6c1fa0986172b.
Report an issue: GitHub.
Appendix: source
Thrown at core/query_functions/src/date_bin_wallclock.rs:556
))),
ColumnarValue::Scalar(ScalarValue::TimestampNanosecond(
Some(MAYDAY + 60 * 60 * 1_000_000_000),
None,
)),
];
let arg_fields = arg_to_fields(&args);
let result = match udf
.invoke_with_args(ScalarFunctionArgs {
args,
arg_fields,
number_rows: 13,
return_field: return_field(DataType::Timestamp(TimeUnit::Nanosecond, None)),
config_options: default_config_options(),
})
.unwrap()
{
ColumnarValue::Scalar(scalar) => scalar,
_ => panic!("Expected scalar value"),
};
assert_eq!(result, ScalarValue::TimestampNanosecond(Some(MAYDAY), None),);
}
#[test]
fn scalar_value_with_timezone() {
let udf = DateBinWallclockUDF::default();
let tz = Arc::from("America/New_York");
let args = vec![
ColumnarValue::Scalar(ScalarValue::IntervalMonthDayNano(Some(
IntervalMonthDayNano::new(0, 1, 0),
))),
ColumnarValue::Scalar(ScalarValue::TimestampNanosecond(
Some(MAYDAY + 60 * 60 * 1_000_000_000),
Some(Arc::clone(&tz)),
)),
];
let arg_fields = arg_to_fields(&args);View on GitHub (pinned to 06200ef96b)