{"record":{"id":"02c44223a98a3d28","repo":"windmill-labs/windmill","slug":"cannot-parse-optional-parameter","errorCode":null,"errorMessage":"Cannot parse optional parameter: {}","messagePattern":"Cannot parse optional parameter: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-ruby/src/lib.rs","lineNumber":160,"sourceCode":"                                        |e|\n                                        anyhow!(\"Cannot convert default value to json\\n\\tvalue: {unparsed}\\n\\terror: {e}{}\",\n                                            if e.to_string().contains(\"key must be a string\") {\n                                                \"\\n\\nNOTE: If you are trying to declare default hash, use following syntax:\\n { \\\"<key>\\\": <value> }\"\n                                            } else {\n                                                \"\"\n                                            }\n                                        ))?;\n                                    args.push(Arg {\n                                        name: ident.to_owned(),\n                                        typ: json_to_typ(&default, true),\n                                        default: Some(default),\n                                        has_default: true,\n                                        ..Default::default()\n                                    });\n                                }\n                                _ => {\n                                    let Range { start_byte, end_byte, .. } = a.range();\n                                    bail!(\n                                        \"Cannot parse optional parameter: {}\",\n                                        &code.get(start_byte..end_byte).unwrap_or(\"CANNOT DISPLAY\")\n                                    )\n                                }\n                            }\n                        }\n                        let kind = a.kind();\n                        if matches!(\n                            kind,\n                            \"keyword_parameter\" | \"splat_parameter\" | \"hash_splat_parameter\"\n                        ) {\n                            let Range { start_byte, end_byte, .. } = a.range();\n                            bail!(\n                                \" - {}\\n{}s are not supported\",\n                                &code.get(start_byte..end_byte).unwrap_or(\"CANNOT DISPLAY\"),\n                                kind.replace(\"_\", \" \")\n                            );\n                        }","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-ruby/src/lib.rs#L142-L178","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","solutions":["Make the parameter a keyword parameter with a default (`def main(name: \"default\")`) which the parser supports","Remove the optional parameter and hardcode the default inside the function body","Pass the value explicitly as a Windmill script argument instead of relying on Ruby defaults"],"exampleFix":"// before\ndef main(limit = 10)\n// after\ndef main(limit: 10)","handlingStrategy":"try-catch","validationCode":"# ensure main only uses supported keyword params with simple defaults\ndef main(a: 1, b: \"x\"); end","typeGuard":null,"tryCatchPattern":"match parse_ruby_sig_meta(code) {\n  Err(e) if e.to_string().starts_with(\"Cannot parse optional parameter\") =>\n    eprintln!(\"simplify the main signature: {e}\"),\n  Err(e) => return Err(e),\n  Ok(meta) => { /* proceed */ }\n}","preventionTips":["Use keyword parameters with literal defaults in `def main`","Avoid optional positional parameters in Windmill Ruby scripts","Run the parser against new scripts during development"],"tags":["ruby","parser","script-signatures"],"backgroundTag":"unsupported-optional-parameter","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}