{"record":{"id":"696c5ab691ac7199","repo":"windmill-labs/windmill","slug":"cannot-parse-argument-ident","errorCode":null,"errorMessage":"Cannot parse argument ident","messagePattern":"Cannot parse argument ident","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/parsers/windmill-parser-nu/src/lib.rs","lineNumber":75,"sourceCode":"\n    let mut compensate_lookahead = 0;\n    for (i, batch) in batches.iter().enumerate() {\n        // parse_default can lookahead and if it does we need to compensate\n        // otherwise we would try to parse data already parsed but not yielded by parse_default\n        if compensate_lookahead > 0 {\n            compensate_lookahead -= 1;\n            continue;\n        }\n\n        let type_start = batch.find(\":\");\n        let default_start = batch.find(\"=\");\n\n        let (name, typ, default) = match (type_start, default_start) {\n            (None, None) => (batch.trim(), None, None),\n            (None, Some(d)) => (\n                batch\n                    .get(0..d)\n                    .ok_or(anyhow!(\"Cannot parse argument ident\"))?\n                    .trim(),\n                None,\n                Some(parse_default(\n                    &batch\n                        .get(d..)\n                        .ok_or(anyhow!(\"Cannot parse default value for argument\"))?,\n                    &batches,\n                    i,\n                    &mut compensate_lookahead,\n                )?),\n            ),\n            (Some(t), None) => (\n                batch\n                    .get(0..t)\n                    .ok_or(anyhow!(\"Cannot parse argument ident\"))?\n                    .trim(),\n                Some(parse_type(\n                    &batch","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/parsers/windmill-parser-nu/src/lib.rs#L57-L93","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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] {}`.","Check the file encoding: re-save the script as UTF-8 without mangled multibyte sequences near `:` or `=` in the argument list.","If a multibyte argument name is desired, quote or rename it — the parser expects simple identifiers optionally followed by `?`, `: type`, and/or `= default`.","Upgrade/redeploy the script through the Windmill UI or `wmill` CLI so the stored script content matches a parseable signature."],"exampleFix":"// before (unparseable ident around '=')\ndef main [🚀 = 1] { $\"x is ($x)\" }\n\n// after\ndef main [x: int = 1] { $\"x is ($x)\" }","handlingStrategy":"validation","validationCode":"// Validate a Nushell script's main signature args before calling parse_nu_signature\nfn validate_nu_args(code: &str) -> Result<(), String> {\n    let args = code\n        .split(\"def main\")\n        .nth(1)\n        .and_then(|r| r.split('[').nth(1))\n        .and_then(|r| r.split(']').next())\n        .ok_or(\"no def main [ ... ] args found\")?;\n    if !code.is_char_boundary(0) {\n        return Err(\"invalid UTF-8 boundaries\".into());\n    }\n    for batch in args.split(',') {\n        let b = batch.trim();\n        if b.is_empty() { continue; }\n        if let Some(d) = b.find('=') {\n            if !b.is_char_boundary(d) || b.get(0..d).is_none() {\n                return Err(format!(\"unparseable ident in argument: {b:?}\"));\n            }\n            if b.get(d..).unwrap_or(\"\").trim_start_matches('=').trim().is_empty() {\n                return Err(format!(\"argument {b:?} has '=' with no default value\"));\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn has_sliceable_ident(batch: &str, d: usize) -> bool {\n    batch.is_char_boundary(d) && batch.get(0..d).map_or(false, |s| !s.trim().is_empty())\n}","tryCatchPattern":"match parse_nu_signature(&nu_code) {\n    Ok(sig) => deploy(sig),\n    Err(e) if e.to_string().contains(\"Cannot parse argument ident\") => {\n        eprintln!(\"bad arg ident in def main: {e}; check argument names before '='\");\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Keep `def main` argument identifiers plain ASCII","Always provide a value after `=` for arguments with defaults","Parse the script in a real Nushell REPL before deploying","Save scripts as UTF-8 and avoid pasting through encoders that mangle multibyte chars"],"tags":["nushell","parser","signature","windmill"],"backgroundTag":"nu-signature-parse-failed","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"}