windmill-labs/windmill · error
typed records are not supported, use `ident: record`
Error message
typed records are not supported, use `ident: record`
What it means
Nushell allows typed records like `record<name: string>` as parameter types. Windmill's parser supports the bare `record` type only (mapped to an open object); any type string containing `record<` is rejected with guidance to use the untyped form. The structured inner schema cannot be represented in Windmill's ObjectType here.
Source
Thrown at backend/parsers/windmill-parser-nu/src/lib.rs:183
"number" => Typ::Float,
"record" => Typ::Object(ObjectType::new(None, Some(vec![]))),
"table" => Typ::List(Box::new(Typ::Object(ObjectType::new(None, Some(vec![]))))),
"nothing" => Typ::Unknown,
// TODO: needs additional work on literal parsing
// "binary" => Typ::Bytes,
"datetime" => Typ::Datetime,
"any" => Typ::Unknown,
"bool" => Typ::Bool,
// Lists
"list" | "list<any>" | "list<nothing>" => Typ::List(Box::new(Typ::Unknown)),
"list<number>" => Typ::List(Box::new(Typ::Float)),
"list<bool>" => Typ::List(Box::new(Typ::Bool)),
"list<string>" => Typ::List(Box::new(Typ::Str(None))),
// list<float/int> is not supported
// Records and Tables
// TODO: Support in V1?
s if s.contains("record<") => {
bail!("typed records are not supported, use `ident: record`")
}
s if s.contains("table<") => {
bail!("typed tables are not supported, use `ident: table`")
}
s => bail!("{s} is not supported"),
};
Ok(typ)
}
fn parse_default(
content: &str,
ctx: &[&str],
i: usize,
skip: &mut usize,
) -> anyhow::Result<Value> {
let mut c = content.replace("=", "").trim().to_owned();
fn parse_object_literal(
(open, close): (char, char),View on GitHub (pinned to e474e8803c)
Solutions
- Change the type to plain `record` and validate fields inside the script body.
- Use `any` and parse/validate the incoming JSON object manually in the script.
- Model the structured data as a Windmill resource or a JSON object input via a `dict`-like convention if the platform offers it.
- Keep the typed record for local use but strip the type parameters in the deployed `def main` signature.
Example fix
// before
def main [user: record<name: string, age: int>]
// after
def main [user: record] {
let name = $user.name? | default ""
} Defensive patterns
Strategy: validation
Validate before calling
function validateNoTypedRecords(code) {
const m = code.match(/def\s+main\s*\[([^\]]*)\]/);
if (m && /record</.test(m[1])) return 'typed records (record<...>) are not supported; use bare `record` and validate fields in the body';
return null;
} Try / catch
try {
const sig = parseNuSignature(source);
} catch (e) {
if (String(e).includes('typed records are not supported')) {
throw new Error('Change the annotation to `record` and validate inner fields inside the script');
}
throw e;
} Prevention
- Use bare `record` (or `any`) for object parameters in entrypoints
- Do field validation in the script body with `| default` / explicit checks
- Keep typed records for internal helpers, never for def main params
When it happens
Trigger: Declaring `def main [cfg: record<name: string, retries: int>]` — any parameter type containing `record<` — when the signature is parsed.
Common situations: Modern Nushell scripts using typed record annotations for IDE/validation benefits being deployed to Windmill; upgrading Nushell and adopting typed records in existing scripts.
Related errors
- Parsing error `:` should be before `=` it likely means you a
- typed tables are not supported, use `ident: table`
- {s} is not supported
- Unexpected Java type node kind: {} for '{}'. This type is no
- Cannot find main function.
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/82927fc4b0684cd8.
Report an issue: GitHub.