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

  1. Fix the prebuild expression so it is valid Rust after `$`->`i` replacement
  2. Ensure only `$1..$n` placeholders matching actual arguments are used
  3. 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

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


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/52d9eb8050dfc950. Report an issue: GitHub.