{"record":{"id":"5f568eb248e78537","repo":"risingwavelabs/risingwave","slug":"does-not-support-struct-array-map-vector-js","errorCode":null,"errorMessage":"{} does not support struct, array, map, vector, jsonb for comparison argument, got {}","messagePattern":"(.+?) does not support struct, array, map, vector, jsonb for comparison argument, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/optimizer/plan_node/logical_agg.rs","lineNumber":808,"sourceCode":"                } else {\n                    let new_agg_call = AggCall {\n                        order_by: OrderBy::any(),\n                        ..agg_call\n                    };\n                    Ok(push_agg_call(new_agg_call)?.into())\n                }\n            }\n            AggType::Builtin(PbAggKind::ArgMin | PbAggKind::ArgMax) => {\n                let mut agg_call = agg_call;\n\n                let comparison_arg_type = agg_call.args[1].return_type();\n                match comparison_arg_type {\n                    DataType::Struct(_)\n                    | DataType::List(_)\n                    | DataType::Map(_)\n                    | DataType::Vector(_)\n                    | DataType::Jsonb => {\n                        bail!(format!(\n                            \"{} does not support struct, array, map, vector, jsonb for comparison argument, got {}\",\n                            agg_call.agg_type.to_string(),\n                            comparison_arg_type\n                        ));\n                    }\n                    _ => {}\n                }\n\n                let not_null_exprs: Vec<ExprImpl> = agg_call\n                    .args\n                    .iter()\n                    .map(|arg| -> Result<ExprImpl> {\n                        Ok(FunctionCall::new(ExprType::IsNotNull, vec![arg.clone()])?.into())\n                    })\n                    .try_collect()?;\n\n                let comparison_expr = agg_call.args[1].clone();\n                let mut order_exprs = vec![OrderByExpr {","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/optimizer/plan_node/logical_agg.rs#L790-L826","documentation":"Certain aggregate call rewrites (in general_rewrite_agg_call) compare arguments (e.g. MIN/MAX-style comparison), and composite types are not comparable there. When the comparison argument's DataType is Struct, List, Map, Vector, or Jsonb, the planner bails with this error naming the aggregate type and the offending type.","triggerScenarios":"A query such as SELECT min(struct_col) FROM ... (or max/other comparison-based agg over a nested/array/map/jsonb column) planned through the frontend.","commonSituations":"Aggregating JSONB payloads from CDC sources; MIN/MAX over ARRAY or STRUCT columns produced by row() literals; schema drift making a column jsonb.","solutions":["Extract a comparable scalar field before aggregating, e.g. min((obj).field) or min(jsonb_col->>'key').","Cast the column to a comparable type if semantics allow (e.g. jsonb ->> 'k' as text).","Use a different aggregate or window/ORDER BY pattern that supports the type."],"exampleFix":"// before\nSELECT max(data) FROM t; -- data is jsonb\n// after\nSELECT max(data->>'created_at') FROM t;","handlingStrategy":"validation","validationCode":"// Check column types before using MIN/MAX-style comparison aggregates\nconst unsupported = new Set(['struct', 'list', 'map', 'vector', 'jsonb']);\nif (unsupported.has(colType)) {\n  throw new Error(`Cannot aggregate ${colName} of type ${colType} with a comparison aggregate; extract a scalar field first`);\n}","typeGuard":"const isComparableScalar = (t: string): boolean => !['struct','list','map','vector','jsonb'].includes(t);","tryCatchPattern":"try {\n  await client.query('SELECT min(data) FROM t');\n} catch (e) {\n  if (String(e.message).includes('does not support struct, array, map, vector, jsonb')) {\n    await client.query(\"SELECT min(data->>'key') FROM t\");\n  } else throw e;\n}","preventionTips":["Never apply min/max directly to jsonb/struct/array columns.","Extract and cast the needed scalar field in the SELECT list.","Keep source schemas typed so columns don't silently become jsonb."],"tags":["risingwave","sql","planner","aggregation","unsupported-type"],"backgroundTag":"unsupported-operation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}