windmill-labs/windmill · error

Cannot parse argument ident

Error message

Cannot parse argument ident

What it means

This error comes from parse_nu_signature in windmill-parser-nu, which extracts the argument list of the `def main [...]` function of a Nushell script. After locating the `=` marking a default value in an argument batch, it slices the batch with `batch.get(0..d)` to isolate the argument identifier; if the byte range is not sliceable (e.g. `d` is not a UTF-8 char boundary or the slice is out of bounds), `str::get` returns None and this anyhow error is raised instead of panicking.

Source

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

    let mut compensate_lookahead = 0;
    for (i, batch) in batches.iter().enumerate() {
        // parse_default can lookahead and if it does we need to compensate
        // otherwise we would try to parse data already parsed but not yielded by parse_default
        if compensate_lookahead > 0 {
            compensate_lookahead -= 1;
            continue;
        }

        let type_start = batch.find(":");
        let default_start = batch.find("=");

        let (name, typ, default) = match (type_start, default_start) {
            (None, None) => (batch.trim(), None, None),
            (None, Some(d)) => (
                batch
                    .get(0..d)
                    .ok_or(anyhow!("Cannot parse argument ident"))?
                    .trim(),
                None,
                Some(parse_default(
                    &batch
                        .get(d..)
                        .ok_or(anyhow!("Cannot parse default value for argument"))?,
                    &batches,
                    i,
                    &mut compensate_lookahead,
                )?),
            ),
            (Some(t), None) => (
                batch
                    .get(0..t)
                    .ok_or(anyhow!("Cannot parse argument ident"))?
                    .trim(),
                Some(parse_type(
                    &batch

View on GitHub (pinned to e474e8803c)

Solutions

  1. Open the Nushell script and inspect the `def main` argument that carries a default value (`=`); fix or rewrite the argument identifier as plain ASCII, e.g. `def main [x = 1] {}`.
  2. Check the file encoding: re-save the script as UTF-8 without mangled multibyte sequences near `:` or `=` in the argument list.
  3. If a multibyte argument name is desired, quote or rename it — the parser expects simple identifiers optionally followed by `?`, `: type`, and/or `= default`.
  4. Upgrade/redeploy the script through the Windmill UI or `wmill` CLI so the stored script content matches a parseable signature.

Example fix

// before (unparseable ident around '=')
def main [🚀 = 1] { $"x is ($x)" }

// after
def main [x: int = 1] { $"x is ($x)" }
Defensive patterns

Strategy: validation

Validate before calling

// Validate a Nushell script's main signature args before calling parse_nu_signature
fn validate_nu_args(code: &str) -> Result<(), String> {
    let args = code
        .split("def main")
        .nth(1)
        .and_then(|r| r.split('[').nth(1))
        .and_then(|r| r.split(']').next())
        .ok_or("no def main [ ... ] args found")?;
    if !code.is_char_boundary(0) {
        return Err("invalid UTF-8 boundaries".into());
    }
    for batch in args.split(',') {
        let b = batch.trim();
        if b.is_empty() { continue; }
        if let Some(d) = b.find('=') {
            if !b.is_char_boundary(d) || b.get(0..d).is_none() {
                return Err(format!("unparseable ident in argument: {b:?}"));
            }
            if b.get(d..).unwrap_or("").trim_start_matches('=').trim().is_empty() {
                return Err(format!("argument {b:?} has '=' with no default value"));
            }
        }
    }
    Ok(())
}

Type guard

fn has_sliceable_ident(batch: &str, d: usize) -> bool {
    batch.is_char_boundary(d) && batch.get(0..d).map_or(false, |s| !s.trim().is_empty())
}

Try / catch

match parse_nu_signature(&nu_code) {
    Ok(sig) => deploy(sig),
    Err(e) if e.to_string().contains("Cannot parse argument ident") => {
        eprintln!("bad arg ident in def main: {e}; check argument names before '='");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling parse_nu_signature on a Nushell script whose main-args line contains a `=` at a byte offset that cannot yield a valid `0..d` slice — practically, a malformed or corrupted argument token around the default-value marker (e.g. multibyte characters interleaved so the `=` index is not a char boundary, or an argument line like `x= ` where the ident portion cannot be extracted).

Common situations: A Nushell script deployed to Windmill whose `def main` argument list was hand-edited or pasted with mangled encoding (e.g. an argument like `🚀=` with emoji/multibyte chars around the `=`), so the parser cannot cut out the identifier before the default-value marker.

Related errors


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