risingwavelabs/risingwave · error
invalid struct type
Error message
invalid struct type
What it means
The `data_type` helper in src/expr/macro/src/gen.rs converts a type string (from function signatures like `struct<a int,b varchar>`) into a `DataType` TokenStream. Strings starting with `struct<` are parsed as a StructType via `DataType::Struct(#ty.parse().expect("invalid struct type"))`; if the text after `struct<` is not a valid serialized struct type, the expect panics during macro expansion.
Source
Thrown at src/expr/macro/src/gen.rs:1471
"anyarray" => quote! { SigDataType::AnyArray },
"anymap" => quote! { SigDataType::AnyMap },
"vector" => quote! { SigDataType::Vector },
"struct" => quote! { SigDataType::AnyStruct },
_ if ty.starts_with("struct") && ty.contains("any") => quote! { SigDataType::AnyStruct },
_ => {
let datatype = data_type(ty);
quote! { SigDataType::Exact(#datatype) }
}
}
}
fn data_type(ty: &str) -> TokenStream2 {
if let Some(ty) = ty.strip_suffix("[]") {
let inner_type = data_type(ty);
return quote! { DataType::list(#inner_type) };
}
if ty.starts_with("struct<") {
return quote! { DataType::Struct(#ty.parse().expect("invalid struct type")) };
}
let variant = format_ident!("{}", types::data_type(ty));
// TODO: enable the check
// assert!(
// !matches!(ty, "any" | "anyarray" | "anymap" | "struct"),
// "{ty}, {variant}"
// );
quote! { DataType::#variant }
}
/// Extract multiple output types.
///
/// ```ignore
/// output_types("int4") -> ["int4"]
/// output_types("struct<key varchar, value jsonb>") -> ["varchar", "jsonb"]
/// ```
fn output_types(ty: &str) -> Vec<&str> {View on GitHub (pinned to 6469eb736d)
Solutions
- Fix the `struct<...>` string so it matches the StructType parse format, e.g. `struct<a int,b varchar>` with matching field-name/type pairs and a closing `>`.
- Verify against existing struct-typed function declarations in the repo and copy a known-good example.
- If a custom/nested shape is needed, build the type with `type_infer` returning a computed `DataType` instead of the inline struct string.
Example fix
// before - missing type after field name breaks the parse
#[function("f(struct<a int,b>)")]
// after
#[function("f(struct<a int,b varchar>)")] Defensive patterns
Strategy: validation
Validate before calling
// Validate struct type strings before putting them in a signature
fn valid_struct_type(s: &str) -> bool {
s.starts_with("struct<")
&& s.ends_with('>')
&& s[7..s.len() - 1].split(',').all(|f| {
let mut it = f.trim().split_whitespace();
it.next().map(|n| !n.is_empty()).unwrap_or(false).then(|| ()).and_then(|_| it.next()).is_some()
})
}
assert!(valid_struct_type("struct<a int,b varchar>")); Prevention
- Use the exact `struct<field type,field type>` serialization the macro expects, always with a closing `>`.
- Copy struct type strings from existing declarations instead of writing them from scratch.
- For complex shapes, prefer a `type_infer` fn returning DataType::Struct built programmatically.
When it happens
Trigger: Declaring a function signature whose argument or return type is `struct<...>` with malformed inner syntax — missing closing `>`, bad field specifiers, or a struct literal that the StructType parser cannot deserialize.
Common situations: Hand-writing struct types in `#[function("f(struct<a int>)")]-style signatures; typos in the field/type syntax; copying struct type strings between formats that use different serialization.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- You can't use the macro on this type
- Expected #[serde_prefix_all(skip)]
- type inference function cannot be automatically derived. You
- multiple arguments are not supported for non-option function
- expect `impl Iterator` in return type
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/c70805cbfe2fc0ff.
Report an issue: GitHub.