windmill-labs/windmill · error · Error
${main_name} function is missing
Error message
${main_name} function is missing What it means
Thrown from the generated `run()` wrapper when the script's main entrypoint (named by main_name, typically `main`) is undefined or not a function. The worker builds a wrapper that calls `{main_name}(...argsArr)`, and guards it so that a script without the expected exported entry function fails with a clear message instead of a confusing 'undefined is not a function' TypeError.
Source
Thrown at backend/windmill-worker/src/deno_executor.rs:355
function argsObjToArr({{ {spread} }}) {{
return [ {spread} ];
}}
BigInt.prototype.toJSON = function () {{
return this.toString();
}};
function isAsyncIterable(obj) {{
return obj != null && typeof obj[Symbol.asyncIterator] === 'function';
}}
async function run() {{
{dates}
{preprocessor}
const argsArr = argsObjToArr(args);
if ({main_name} === undefined || typeof {main_name} !== 'function') {{
throw new Error("{main_name} function is missing");
}}
let res: any = await {main_name}(...argsArr);
if (isAsyncIterable(res)) {{
for await (const chunk of res) {{
console.log("WM_STREAM: " + chunk.replace(/\n/g, '\\n'));
}}
res = null;
}}
const res_json = JSON.stringify(res ?? null, (key, value) => typeof value === 'undefined' ? null : value);
await Deno.writeTextFile("result.json", res_json);
Deno.exit(0);
}}
try {{
await run();
}} catch(e) {{
let err = {{ message: e.message, name: e.name, stack: e.stack }};
let step_id = Deno.env.get("WM_FLOW_STEP_ID");
if (step_id) {{View on GitHub (pinned to e474e8803c)
Solutions
- Export a function named `main` from the script: `export async function main(args) { ... }`
- Check the script's entrypoint setting (advanced options) matches the exported function name if you intentionally use a different name
- Add the missing `export` keyword — `function main()` alone is not visible to the wrapper
- Ensure the script was saved/deployed so the running version actually contains the export
Example fix
// before
async function main(x: number) {
return x * 2;
} // not exported
// after
export async function main(x: number) {
return x * 2;
} Defensive patterns
Strategy: validation
Validate before calling
// guard in the script file itself:
if (typeof main !== 'function') {
throw new Error('script must export a `main` function');
} Type guard
function hasMain(mod: Record<string, unknown>): mod is { main: (...args: unknown[]) => unknown } {
return typeof mod.main === 'function';
} Prevention
- Always start Deno scripts from a Windmill template containing `export async function main(...)`
- Never rename `main` without updating the script's entrypoint setting in advanced options
- Add a CI check that each .ts script exports `main` before deploy (`wmill script push` validation)
When it happens
Trigger: Executing any Deno/TypeScript script whose source does not export a function with the configured entrypoint name (usually `main`) — e.g. no export at all, `export function Main()` with different casing, or the export is a non-callable value.
Common situations: New script created from an empty template without a `main` export; renaming `main` to something else while the script metadata still points to `main`; forgetting the `export` keyword; writing `main` as a top-level side-effect script with no function; language/entrypoint mismatch after switching script kind.
Related errors
- preprocessor function is missing
- ${main_name} function is missing
- The connection check did not run. Is a worker listening to t
- could not create dir '{directory_path}': {e}
- failed to execute replace_ephemeral command: {}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/0243ad59cdac28c1.
Report an issue: GitHub.