risingwavelabs/risingwave · error
expects a struct array ref
Error message
expects a struct array ref
What it means
The field-access expression's array evaluation expects its evaluated input to be a StructArray; anything else (e.g. a ListArray or other variant) triggers this anyhow-based error. It indicates the input expression's type didn't match the struct-field-access requirement.
Source
Thrown at src/expr/impl/src/scalar/field.rs:45
pub struct FieldExpression<E> {
return_type: DataType,
input: E,
index: usize,
}
impl<E: ExpressionInfo> ExpressionInfo for FieldExpression<E> {
fn return_type(&self) -> DataType {
self.return_type.clone()
}
}
macro_rules! eval_field {
($mode:ident, $this:expr, $input:expr) => {{
let array = risingwave_expr::forward!($mode, $this.input, eval($input))?;
if let ArrayImpl::Struct(struct_array) = array.as_ref() {
Ok(struct_array.field_at($this.index).clone())
} else {
Err(anyhow!("expects a struct array ref").into())
}
}};
}
macro_rules! eval_row_field {
($mode:ident, $this:expr, $input:expr) => {{
let struct_datum = risingwave_expr::forward!($mode, $this.input, eval_row($input))?;
struct_datum
.map(|s| match s {
ScalarImpl::Struct(v) => Ok(v.fields()[$this.index].clone()),
_ => Err(anyhow!("expects a struct array ref").into()),
})
.transpose()
.map(|x| x.flatten())
}};
}
impl<E: SyncExpression> SyncExpression for FieldExpression<E> {View on GitHub (pinned to 6469eb736d)
Solutions
- Ensure the input expression's return type is a STRUCT before applying field access.
- Unnest lists first (e.g. FLATTEN/unnest) before accessing struct fields inside them.
- Verify the source schema: the accessed column must genuinely be a struct type.
Example fix
// before field_access(input_list_expr, index) // input is ListArray // after field_access(unnest_or_cast_to_struct(input_list_expr), index)
Defensive patterns
Strategy: validation
Validate before calling
if !matches!(input.return_type(), DataType::Struct(_)) {
return Err("field access requires a struct input".into());
} Type guard
fn is_struct_input(e: &BoxedExpression) -> bool { matches!(e.return_type(), DataType::Struct(_)) } Prevention
- Check the column type in the catalog before writing nested field access.
- Unnest lists before accessing struct fields within them.
- Guard generic expression builders to only create field access on struct-typed inputs.
When it happens
Trigger: Evaluating a field access expression whose input array is not ArrayImpl::Struct — e.g. accessing `.field` on a non-struct column, or after a cast/reorganization changed the input to a list or primitive array.
Common situations: Querying a nested field of a column that is actually a list/array rather than a struct; schema drift where a struct column became a different type; incorrect expr construction in custom planners.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Array error: {0}
- Type mismatched between then clause and case
- Expr error: {0}
- Join key types are not aligned: LHS: {outer_type:?}, RHS: {i
- Join key types are not aligned: LHS: {outer_type:?}, RHS: {i
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/b103c6c420b34127.
Report an issue: GitHub.