windmill-labs/windmill · error

Error parsing sql

Error message

Error parsing sql

What it means

parse_graphql_sig parses GraphQL operation files by regex-extracting `$var: Type` argument declarations; parse_graphql_file returns None when no operation/arguments could be parsed, and the function rejects that with this (misleadingly worded) 'Error parsing sql' message. It means the input was not recognized as a GraphQL operation with parseable arguments, not that SQL was involved.

Source

Thrown at backend/parsers/windmill-parser-graphql/src/lib.rs:27

use serde_json::json;

use windmill_parser::{Arg, MainArgSignature, ObjectType, Typ};

pub fn parse_graphql_sig(code: &str) -> anyhow::Result<MainArgSignature> {
    let parsed = parse_graphql_file(&code)?;
    if let Some(x) = parsed {
        let args = x;
        Ok(MainArgSignature {
            star_args: false,
            star_kwargs: false,
            args,
            auto_kind: None,
            has_preprocessor: None,
            ..Default::default()
        })
    } else {
        Err(anyhow!("Error parsing sql".to_string()))
    }
}

lazy_static::lazy_static! {
    static ref RE_ARG_GRAPHQL: Regex = Regex::new(r#"\$(\w+)\s*:\s*(?:(\w+)(!)?|\[(\w+)!?\])(!)?\s*(?:=\s*"?(\w+)"?\s*)?"#).unwrap();
}

fn parse_graphql_file(code: &str) -> anyhow::Result<Option<Vec<Arg>>> {
    let mut args: Vec<Arg> = vec![];

    for cap in RE_ARG_GRAPHQL.captures_iter(code) {
        let name = cap.get(1).map(|x| x.as_str().to_string()).unwrap();
        let mut typ = cap.get(2).map(|x| x.as_str().to_string());

        let parsed_typ = if typ.is_none() {
            let inner_typ = cap.get(4).map(|x| x.as_str().to_string());
            typ = inner_typ.clone().map(|x| format!("[{}]", x.to_string()));
            Typ::List(Box::new(parse_graphql_typ(inner_typ.unwrap().as_str())))

View on GitHub (pinned to e474e8803c)

Solutions

  1. Verify the script is actually GraphQL, not SQL — paste it into a GraphQL script, not a SQL one
  2. Declare arguments in the standard form `$var: Type!` (or `[Type!]`) inside the operation, e.g. `query Q($id: ID!) { ... }`
  3. Check for typos in variable declarations: the `$` prefix, colon, and capitalized type are all required for the regex to match
  4. Wrap the query in an explicit `query`/`mutation` operation definition if detection still fails

Example fix

// before
{ user(id: $id) { name } }
// after
query GetUser($id: ID!) {
  user(id: $id) { name }
}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check: the script must contain at least one `$var: Type` argument declaration
let re = regex::Regex::new(r"\$\w+\s*:").unwrap();
fn has_graphql_args(code: &str, re: &regex::Regex) -> bool {
    re.is_match(code)
}

Type guard

fn looks_like_graphql_operation(code: &str) -> bool {
    code.contains("query ") || code.contains("mutation ") || code.contains("subscription ")
        || code.trim_start().starts_with('{')
}

Try / catch

match parse_graphql_sig(code) {
    Ok(sig) => sig,
    Err(e) if e.to_string() == "Error parsing sql" => {
        // misnamed legacy message: means no GraphQL args were detected
        bail!("no $var: Type arguments found — is this really a GraphQL script?")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: do_graphql on a script whose content contains no `$var: Type` matches and no recognizable operation — empty query, wrong-language content pasted into a GraphQL script, or variable declarations shaped so the argument regex misses everything.

Common situations: Pasting a SQL script into a GraphQL script slot (the error text betrays the copy-paste origin); variable declarations with typos (`$id int` without a colon, missing `$`); anonymous shorthand queries `{ ... }` that still need standard `$var: Type` args; exotic types like nested `[Inner!]!]` the regex cannot capture.

Related errors


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