risingwavelabs/risingwave · error
invalid prebuild syntax
Error message
invalid prebuild syntax
What it means
The macro's `prebuild` option accepts an expression template where `$1`, `$2` map to argument variables `i1`, `i2`. The string is rewritten and parsed as Rust TokenStream; if the expression does not parse, the macro panics with `invalid prebuild syntax` at proc-macro expansion time.
Source
Thrown at src/expr/macro/src/gen.rs:287
"T" | "T1" | "T2" | "T3" => format!(": Option<{}>", types::owned_type(&self.ret))
.parse()
.unwrap(),
_ => quote! {},
};
let ret_array_type = format_ident!("{}", types::array_type(&self.ret));
let builder_type = format_ident!("{}Builder", types::array_type(&self.ret));
let prebuilt_arg_type = match &self.prebuild {
Some(s) if optimize_const => s.split("::").next().unwrap().parse().unwrap(),
_ => quote! { () },
};
let prebuilt_arg_value = match &self.prebuild {
// example:
// prebuild = "RegexContext::new($1)"
// return = "RegexContext::new(i1)"
Some(s) => s
.replace('$', "i")
.parse()
.expect("invalid prebuild syntax"),
None => quote! { () },
};
let prebuild_const = if self.prebuild.is_some() && optimize_const {
let build_general = self.generate_build_scalar_function(user_fn, false)?;
quote! {{
let build_general = #build_general;
#(
// try to evaluate constant for prebuilt arguments
let #prebuilt_inputs = match children[#prebuilt_indices].eval_const() {
Ok(s) => s,
// prebuilt argument is not constant, fallback to general
Err(_) => return build_general(return_type, children),
};
// get reference to the constant value
let #prebuilt_inputs = match &#prebuilt_inputs {
Some(s) => s.as_scalar_ref_impl().try_into()?,
// the function should always return null if any const argument is null
None => return Ok(risingwave_expr::expr::LiteralExpression::new(View on GitHub (pinned to 6469eb736d)
Solutions
- Fix the prebuild expression so it is valid Rust after `$`->`i` replacement
- Ensure only `$1..$n` placeholders matching actual arguments are used
- Replace the `.expect` with a proper proc-macro `syn::Error` for a better message
Example fix
// before prebuild = "RegexContext::new($1 $2)" // after prebuild = "RegexContext::new($1, $2)"
Defensive patterns
Strategy: validation
Validate before calling
// validate prebuild parses before feeding to macro (mentally or in a test):
let expr: proc_macro2::TokenStream = "RegexContext::new($1)".replace('$', "i").parse().expect("invalid prebuild syntax"); Prevention
- Test proc-macro expansion with `cargo expand` when adding prebuild
- Only use $1..$n placeholders matching declared arguments
- Keep prebuild expressions minimal and well-formed Rust
When it happens
Trigger: Specifying e.g. `prebuild = "RegexContext::new($1)"` with a syntax error, an unbalanced delimiter, or a stray `$n`/identifier that yields invalid Rust tokens after replacement.
Common situations: Typo in a prebuild expression like `RegexContext:new($1)`; referencing a nonexistent `$3` producing identifiers like `i3` out of scope; hand-editing prebuild strings.
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
- expected literal
- You can't use the macro on this type
- Expected #[serde_prefix_all(skip)]
- Invalid partition fields: {} HINT: Supported formats are col
- type inference for this function should be specially handled
AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11).
Data as JSON: /api/errors/52d9eb8050dfc950.
Report an issue: GitHub.