windmill-labs/windmill · error

Parsing error

Error message

Parsing error

What it means

Raised by parse_nu_signature in windmill-parser-nu. The Nu lexer produces tokens carrying byte spans into the source; the code slices `src.get(s.start..s.end)` and errors when the span does not index into the source string (returns None). This happens when the lexer's byte span is misaligned with the UTF-8 string slice — typically because the source contains multi-byte characters and a span boundary lands mid-codepoint, or because the lexer emitted an inconsistent/zero-width span.

Source

Thrown at backend/parsers/windmill-parser-nu/src/lib.rs:22

use nu_parser::lex;

use serde_json::{json, Value};
use windmill_parser::{Arg, MainArgSignature, ObjectType, Typ};

pub fn parse_nu_signature(code: &str) -> anyhow::Result<MainArgSignature> {
    let (tokens, ..) = lex(code.as_bytes(), 0, &[], &[], true);
    let src = code.to_owned();
    #[derive(Debug)]
    enum LastToken {
        None,
        Def,
        Main,
        Args(String),
    }
    let mut last_token = LastToken::None;
    for token in tokens {
        let s = token.span;
        let cont = src.get(s.start..s.end).ok_or(anyhow!("Parsing error"))?;
        last_token = match last_token {
            LastToken::None if cont == "def" => LastToken::Def,
            LastToken::Def if cont == "main" => LastToken::Main,
            LastToken::Main => {
                LastToken::Args(cont.get(1..(cont.len() - 1)).unwrap_or("Error").to_owned())
            }
            LastToken::Args(_) => break,
            _ => LastToken::None,
        };
    }

    let LastToken::Args(args) = last_token else {
        bail!("Cannot find main function.");
    };

    let mut sig = MainArgSignature::default();
    sig.auto_kind = None;

View on GitHub (pinned to e474e8803c)

Solutions

  1. Remove or replace non-ASCII characters (accents, emoji, CJK, smart quotes) before the `def main` signature — especially inside comments — or move `def main` to the top of the file.
  2. ASCII-fold the offending text: rewrite `# café` as `# cafe`, replace curly quotes with straight ones.
  3. Strip a leading UTF-8 BOM before parsing: pass `code.trim_start_matches('\u{feff}')` into parse_nu_signature.
  4. If the input is pure ASCII and it still fails, it's a span/lexer bug: check your nu-parser crate version against the one windmill-parser-nu was built for, and file an issue with the exact source.

Example fix

// before (non-ASCII comment shifts/invalidates token byte spans)
# naïve script — café setup 🎉
def main [x: int] { $x }

// after (ASCII-only preamble, or strip BOM before calling)
# naive script - cafe setup
def main [x: int] { $x }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the source is BOM-free and ASCII-safe in the regions the lexer spans before parsing:
fn prepare_for_nu_parser(code: &str) -> String {
    code.trim_start_matches('\u{feff}').to_string()
}
fn has_non_ascii(code: &str) -> bool {
    code.chars().any(|c| !c.is_ascii())
}

Try / catch

match parse_nu_signature(&prepare_for_nu_parser(code)) {
    Ok(sig) => sig,
    Err(e) if e.to_string() == "Parsing error" => {
        // likely non-ASCII content invalidating token spans: retry ASCII-only
        parse_nu_signature(&code.chars().filter(|c| c.is_ascii()).collect::<String>())
            .unwrap_or_default()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling parse_nu_signature on Nu source where the `def main` region is preceded/interleaved by multi-byte UTF-8 characters (e.g. accented letters, CJK, emoji) such that a token's byte span start..end is not a valid char boundary for str::get, causing the slice to return None. Also possible from lexer edge cases on unusual inputs that yield spans past end-of-input.

Common situations: A Nu script with comments or strings containing non-ASCII characters before the `def main` line; users pasting scripts from editors that include smart quotes or Unicode BOM/whitespace; Nu engine version changes altering token span semantics relative to what this hand-rolled tokenizer walk expects.

Related errors


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