{"record":{"id":"60b446144e34f65e","repo":"windmill-labs/windmill","slug":"invalid-gemfile-do-block","errorCode":null,"errorMessage":"Invalid gemfile do block","messagePattern":"Invalid gemfile do block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-ruby/src/lib.rs","lineNumber":100,"sourceCode":"\n                    lazy_static::lazy_static! {\n                        static ref WINDMILL_RE: Regex = Regex::new(r\"(?m)^\\s*require\\s*'windmill/inline'\").unwrap();\n                    }\n\n                    if WINDMILL_RE.find(&code).is_none() {\n                        return Err(anyhow!(\n                            \"`require 'windmill/inline'` is not detected - please add `require 'windmill/inline'` in order to use inline gemfile.\n                Your Gemfile syntax will be compatible with bundler/inline.\"\n                        )\n                        .into());\n                    }\n\n                    return req\n                        // gemfile do_block comes with 'do' and 'end'\n                        // we want to omit these by taking slice\n                        .get(2..(req.len() - 3))\n                        .map(str::to_owned)\n                        .ok_or(anyhow!(\"Invalid gemfile do block\"));\n                }\n            }\n        }\n    }\n    Ok(String::new())\n}\n\n// Function to find the Main method's signature\nfn find_main_signature<'a>(root_node: Node<'a>, code: &str) -> anyhow::Result<Option<Vec<Arg>>> {\n    let mut cursor = root_node.walk();\n    'top_level: for x in root_node.children(&mut cursor) {\n        if x.kind() == \"method\" {\n            let mut args = vec![];\n            for (i, m) in x.children(&mut x.walk()).skip(1).enumerate() {\n                if i == 0\n                    && m.kind() == \"identifier\"\n                    && !m\n                        .utf8_text(code.as_bytes())","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-ruby/src/lib.rs#L82-L118","documentation":"When extracting the gemfile body, `parse_ruby_requirements` takes the AST node text of the `do ... end` block and slices off 2 leading bytes ('do') and 3 trailing bytes ('end') to get the inner requirement lines. If the resulting byte range is invalid (block text shorter than 5 bytes, i.e. `get(2..len-3)` returns None), it raises \"Invalid gemfile do block\".","triggerScenarios":"A `gemfile do ... end` block whose parsed block-node text is too short to slice — e.g. `gemfile do end` (empty body) or `gemfile do end` written on one line where the do_block node text is `\"do end\"` (5 bytes → slice 2..2 is Some, but `\"do\"`/`\"d\\n\"`-like degenerate nodes yield None); also mutated/odd ASTs where the captured node is not a normal do_block.","commonSituations":"Empty `gemfile do end` bodies; scripts where the gemfile block is malformed after tree-sitter parsing; scripts copied with unusual whitespace such that the do_block node text is minimal.","solutions":["Give the gemfile block a non-empty body with at least one `gem 'name'` line","Write the block across multiple lines: `gemfile do\\n  gem 'sinatra'\\nend`","If no gems are needed, delete the gemfile block entirely and use the requirements field instead"],"exampleFix":"// before\ngemfile do end\n// after\ngemfile do\n  gem 'sinatra'\nend","handlingStrategy":"validation","validationCode":"// # Ruby-side pre-check for a usable gemfile body:\n// if code =~ /^\\s*gemfile\\s+do\\s*end\\b/   # empty one-line block\n//   raise \"gemfile block must contain at least one gem line\"\n// end","typeGuard":null,"tryCatchPattern":"match parse_ruby_requirements(code) {\n    Ok(g) => g,\n    Err(e) if e.to_string().contains(\"Invalid gemfile do block\") => {\n        Err(anyhow!(\"your gemfile block has no extractable body: {e}\"))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Write gemfile blocks multi-line with at least one `gem 'name'` line inside","Remove the gemfile block entirely when no inline gems are needed","Keep `do` and `end` on separate lines from the body to preserve the expected AST shape"],"tags":["ruby","gemfile","parser","validation"],"backgroundTag":"invalid-gemfile-block","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"}