windmill-labs/windmill · error

Error parsing code: {}

Error message

Error parsing code: {}

What it means

parse_assets in windmill-parser-py-asset parses the entire Python file with the ruff python_ast Suite::parse before walking it for windmill asset references (s3:// URIs etc.). If the file is not syntactically valid Python, the parse error is wrapped as 'Error parsing code: ...'.

Source

Thrown at backend/parsers/windmill-parser-py-asset/src/lib.rs:12

use rustpython_ast::{Constant, Expr, ExprConstant, Visitor};
use rustpython_parser::{ast::Suite, Parse};
use std::collections::HashMap;
use windmill_parser::asset_parser::{
    asset_was_used, merge_assets, parse_asset_syntax, parse_pipeline_annotations, AssetKind,
    AssetUsageAccessType, ParseAssetsOutput, ParseAssetsResult,
};
use AssetUsageAccessType::*;

pub fn parse_assets(input: &str) -> anyhow::Result<ParseAssetsOutput> {
    let ast = Suite::parse(input, "main.py")
        .map_err(|e| anyhow::anyhow!("Error parsing code: {}", e.to_string()))?;

    let mut assets_finder = AssetsFinder { assets: vec![], var_identifiers: HashMap::new() };
    ast.into_iter()
        .for_each(|stmt| assets_finder.visit_stmt(stmt));

    for (kind, path, _) in assets_finder.var_identifiers.into_values() {
        // if a db = wmill.datatable() was never used (e.g db.query(...)),
        // we still want to register the asset as unknown access type
        if asset_was_used(&assets_finder.assets, (kind, &path)) == false {
            assets_finder.assets.push(ParseAssetsResult {
                kind,
                path,
                access_type: None,
                columns: None,
            });
        }
    }

View on GitHub (pinned to e474e8803c)

Solutions

  1. Read the wrapped message for the exact line/column of the Python syntax error and fix it there.
  2. Validate locally with 'python -m py_compile main.py' before deploying.
  3. Remove leftover template placeholders and smart quotes/invisible characters from pasted code.
  4. Ensure the syntax used matches the Python version the ruff-based parser targets.

Example fix

// before
print "hello"

// after
print("hello")
Defensive patterns

Strategy: validation

Validate before calling

import subprocess, sys, tempfile, os
def validate_python_syntax(code: str) -> None:
    with tempfile.NamedTemporaryFile('w', suffix='.py', delete=False) as f:
        f.write(code); path = f.name
    try:
        subprocess.run([sys.executable, '-m', 'py_compile', path], check=True,
                       capture_output=True)
    except subprocess.CalledProcessError as e:
        raise SystemExit(f'Python syntax invalid:\n{e.stderr.decode()}')
    finally:
        os.unlink(path)

Try / catch

try:
    out = parse_assets(code)
except Exception as e:
    if 'Error parsing code:' in str(e):
        raise RuntimeError(f'Fix Python syntax before asset analysis: {e}') from e
    raise

Prevention

When it happens

Trigger: Calling parse_assets on Python source with syntax errors, Python-version-mismatched syntax (e.g. match statements parsed with an older target), or non-Python content passed in as the script body.

Common situations: Scripts generated by templates with unfilled placeholders, Python 2 style print statements, truncated files from failed writes, or pasted code with smart quotes / invisible characters.

Related errors


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