windmill-labs/windmill · error

Cannot parse optional parameter: {}

Error message

Cannot parse optional parameter: {}

What it means

The Ruby signature parser (windmill-parser-ruby) walks the tree-sitter AST of `def main(...)` to extract parameter metadata. Optional parameters with syntax the parser does not recognize (beyond simple keyword arguments with defaults it handles) cause a bail with the offending parameter text. This keeps signature extraction honest instead of guessing wrong types.

Source

Thrown at backend/parsers/windmill-parser-ruby/src/lib.rs:160

                                        |e|
                                        anyhow!("Cannot convert default value to json\n\tvalue: {unparsed}\n\terror: {e}{}",
                                            if e.to_string().contains("key must be a string") {
                                                "\n\nNOTE: If you are trying to declare default hash, use following syntax:\n { \"<key>\": <value> }"
                                            } else {
                                                ""
                                            }
                                        ))?;
                                    args.push(Arg {
                                        name: ident.to_owned(),
                                        typ: json_to_typ(&default, true),
                                        default: Some(default),
                                        has_default: true,
                                        ..Default::default()
                                    });
                                }
                                _ => {
                                    let Range { start_byte, end_byte, .. } = a.range();
                                    bail!(
                                        "Cannot parse optional parameter: {}",
                                        &code.get(start_byte..end_byte).unwrap_or("CANNOT DISPLAY")
                                    )
                                }
                            }
                        }
                        let kind = a.kind();
                        if matches!(
                            kind,
                            "keyword_parameter" | "splat_parameter" | "hash_splat_parameter"
                        ) {
                            let Range { start_byte, end_byte, .. } = a.range();
                            bail!(
                                " - {}\n{}s are not supported",
                                &code.get(start_byte..end_byte).unwrap_or("CANNOT DISPLAY"),
                                kind.replace("_", " ")
                            );
                        }

View on GitHub (pinned to e474e8803c)

Solutions

  1. Make the parameter a keyword parameter with a default (`def main(name: "default")`) which the parser supports
  2. Remove the optional parameter and hardcode the default inside the function body
  3. Pass the value explicitly as a Windmill script argument instead of relying on Ruby defaults

Example fix

// before
def main(limit = 10)
// after
def main(limit: 10)
Defensive patterns

Strategy: try-catch

Validate before calling

# ensure main only uses supported keyword params with simple defaults
def main(a: 1, b: "x"); end

Try / catch

match parse_ruby_sig_meta(code) {
  Err(e) if e.to_string().starts_with("Cannot parse optional parameter") =>
    eprintln!("simplify the main signature: {e}"),
  Err(e) => return Err(e),
  Ok(meta) => { /* proceed */ }
}

Prevention

When it happens

Trigger: Defining `def main(...)` in a Ruby script with an optional parameter form the parser's match arms don't cover, e.g. an optional positional parameter or an exotic default expression; raised in `find_main_signature` called from `parse_ruby_sig_meta`.

Common situations: Ruby Windmill scripts with `def main(a = nil)` style optional positional args, splat-adjacent defaults, or default expressions the parser wasn't written to handle.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/02c44223a98a3d28. Report an issue: GitHub.