windmill-labs/windmill · error
Invalid gemfile do block
Error message
Invalid gemfile do block
What it means
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".
Source
Thrown at backend/parsers/windmill-parser-ruby/src/lib.rs:100
lazy_static::lazy_static! {
static ref WINDMILL_RE: Regex = Regex::new(r"(?m)^\s*require\s*'windmill/inline'").unwrap();
}
if WINDMILL_RE.find(&code).is_none() {
return Err(anyhow!(
"`require 'windmill/inline'` is not detected - please add `require 'windmill/inline'` in order to use inline gemfile.
Your Gemfile syntax will be compatible with bundler/inline."
)
.into());
}
return req
// gemfile do_block comes with 'do' and 'end'
// we want to omit these by taking slice
.get(2..(req.len() - 3))
.map(str::to_owned)
.ok_or(anyhow!("Invalid gemfile do block"));
}
}
}
}
Ok(String::new())
}
// Function to find the Main method's signature
fn find_main_signature<'a>(root_node: Node<'a>, code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
let mut cursor = root_node.walk();
'top_level: for x in root_node.children(&mut cursor) {
if x.kind() == "method" {
let mut args = vec![];
for (i, m) in x.children(&mut x.walk()).skip(1).enumerate() {
if i == 0
&& m.kind() == "identifier"
&& !m
.utf8_text(code.as_bytes())View on GitHub (pinned to e474e8803c)
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
Example fix
// before gemfile do end // after gemfile do gem 'sinatra' end
Defensive patterns
Strategy: validation
Validate before calling
// # Ruby-side pre-check for a usable gemfile body: // if code =~ /^\s*gemfile\s+do\s*end\b/ # empty one-line block // raise "gemfile block must contain at least one gem line" // end
Try / catch
match parse_ruby_requirements(code) {
Ok(g) => g,
Err(e) if e.to_string().contains("Invalid gemfile do block") => {
Err(anyhow!("your gemfile block has no extractable body: {e}"))
}
Err(e) => Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- `require 'windmill/inline'` is not detected - please add `re
- Aborted from C
- Cannot parse optional parameter: {}
- - {} {}s are not supported
- Failed to parse code
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/60b446144e34f65e.
Report an issue: GitHub.