windmill-labs/windmill · error

Cannot parse type of argument

Error message

Cannot parse type of argument

What it means

parse_nu_signature slices the type annotation of a Nushell main-args argument with `batch.get(t..)`, where `t` is the byte offset of `:`, and passes the result to parse_type. When the range cannot be sliced (str::get returns None) this anyhow error is raised; it guards the extraction of the `: type` portion of the argument.

Source

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

                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
                        .get(t..)
                        .ok_or(anyhow!("Cannot parse type of argument"))?,
                )?),
                None,
            ),
            (Some(t), Some(d)) => {
                if t < d {
                    (
                        batch
                            .get(0..t)
                            .ok_or(anyhow!("Cannot parse argument ident"))?
                            .trim(),
                        Some(parse_type(
                            &batch
                                .get(t..d)
                                .ok_or(anyhow!("Cannot parse type of argument"))?,
                        )?),
                        Some(parse_default(
                            &batch
                                .get(d..)

View on GitHub (pinned to e474e8803c)

Solutions

  1. Ensure every typed argument has complete text after `:` — e.g. `x: string`, not a truncated `x:`.
  2. Compare the script against a working version (git history or hub original) and restore the argument list.
  3. Re-encode the file as UTF-8 without BOM and remove stray bytes around the argument list.
  4. Check the type keyword against the supported list; unsupported types fail later in parse_type with a different message, but malformed bytes around `:` fail here.

Example fix

// before (truncated type token)
def main [x:] { $x }

// after
def main [x: int] { $x }
Defensive patterns

Strategy: validation

Validate before calling

// Ensure each ':' type marker is followed by a supported type keyword
fn validate_nu_types(code: &str) -> Result<(), String> {
    const SUPPORTED: &[&str] = &["string", "int", "float", "number", "record", "table",
        "nothing", "datetime", "any", "bool", "list", "list<any>", "list<nothing>",
        "list<number>", "list<bool>", "list<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")?;
    for batch in args.split(',') {
        let b = batch.trim();
        if let Some(t) = b.find(':') {
            let ty = b.get(t..).unwrap_or("").trim_start_matches(':').trim();
            if ty.is_empty() {
                return Err(format!("missing type after ':' in {b:?}"));
            }
            if !SUPPORTED.contains(&ty) {
                return Err(format!("unsupported type '{ty}' in {b:?}"));
            }
        }
    }
    Ok(())
}

Type guard

fn has_sliceable_type(batch: &str, t: usize) -> bool {
    batch.is_char_boundary(t)
        && batch.get(t..).map_or(false, |s| !s.trim_start_matches(':').trim().is_empty())
}

Try / catch

match parse_nu_signature(&nu_code) {
    Ok(sig) => deploy(sig),
    Err(e) if e.to_string().contains("Cannot parse type of argument") => {
        eprintln!("malformed type annotation in def main args: {e}");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: parse_nu_signature encounters a batch with a `:` type marker at offset `t` such that `get(t..)` is not a valid byte range — e.g. the `:` byte lies at the end of a corrupted token or inside a broken multibyte sequence, so the type text cannot be recovered.

Common situations: Scripts whose argument list was truncated mid-token by a bad save/merge (e.g. `x:` at end of file with lost bytes), or generated signatures with encoding corruption around the type marker.

Related errors


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