windmill-labs/windmill · error · ValueError

{main_override} function is missing

Error message

{main_override} function is missing

What it means

Raised inside the Python wrapper generated by handle_python_job when the script does not define the required entry function (the template's {main_override} is the expected function name, normally `main`). Windmill invokes scripts via main(**args); with no such callable there is nothing to run, so the injected try-block fails the job.

Source

Thrown at backend/windmill-worker/src/python_executor.rs:967

_u=re.compile(r'\\\\|\\u0000')
_us=lambda m:' null ' if m.group(0)[1]=='u' else m.group(0)
_r=lambda m,s='':(_u.sub(_us,s) if '\\u0000' in s else s) if (s:=m.group(0))[0]=='"' else ' null '
replace_invalid_fields=re.compile(r'"(?:\\.|[^"\\])*"|\bNaN\b|-?Infinity')
_fix=lambda s:s if 'Infinity' not in s and 'NaN' not in s and '\\u0000' not in s else re.sub(replace_invalid_fields,_r,s)

result_json = os.path.join(os.path.abspath(os.path.dirname(__file__)), "result.json")

def res_to_json(res, typ):
{res_to_json_body}

try:
    {preprocessor}
    {spread}
    for k, v in list(args.items()):
        if v == '<function call>':
            del args[k]
    if inner_script.{main_override} is None or not callable(inner_script.{main_override}):
        raise ValueError("{main_override} function is missing")
    res = inner_script.{main_override}(**args)
    typ = type(res)
    if hasattr(res, '__iter__') and not isinstance(res, (str, dict, list, bytes, tuple, set, frozenset, range, memoryview, bytearray)) and typ.__name__ != 'DataFrame':
        for chunk in res:
            print("WM_STREAM: " + chunk.replace('\n', '\\n'))
        res = None
    res_json = res_to_json(res, typ)
    with open(result_json, 'w') as f:
        f.write(res_json)
except BaseException as e:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    tb = traceback.format_tb(exc_traceback)
    with open(result_json, 'w') as f:
        err = {{ "message": str(e), "name": e.__class__.__name__, "stack": '\n'.join(tb[1:]) }}
        extra = e.__dict__
        if extra and len(extra) > 0:
            err['extra'] = extra
        flow_node_id = os.environ.get('WM_FLOW_STEP_ID')

View on GitHub (pinned to e474e8803c)

Solutions

  1. Define a function named `main` whose parameters match the script's declared args
  2. Rename the entry function to `main` (or align the configured override with its actual name)
  3. Check the code actually reached the definition — it may sit behind an early return or condition
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at backend/windmill-worker/src/python_executor.rs:967 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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