{"record":{"id":"76f56fa5f12698f2","repo":"windmill-labs/windmill","slug":"the-expression-evaluation-expr-took-too-long-t","errorCode":null,"errorMessage":"The expression evaluation `{expr}` took too long to execute (>{EVAL_TIMEOUT_MS}ms)","messagePattern":"The expression evaluation `(.+?)` took too long to execute \\(>(.+?)ms\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-jseval/src/lib.rs","lineNumber":325,"sourceCode":"            handle.block_on(async move {\n                eval_quickjs_inner(\n                    &expr_clone,\n                    filtered_context,\n                    flow_input_clone,\n                    flow_env_clone,\n                    authed_client_clone,\n                    by_id_clone,\n                    ctx,\n                    context_keys,\n                    memory_limit,\n                )\n                .await\n            })\n        }),\n    )\n    .await\n    .map_err(|_| {\n        anyhow::anyhow!(\n            \"The expression evaluation `{expr}` took too long to execute (>{EVAL_TIMEOUT_MS}ms)\"\n        )\n    })??\n}\n\n/// Default memory cap, in bytes, for a single flow step-input transform eval\n/// (`eval_timeout_quickjs`). Large enough for transforms that build sizeable\n/// arrays; genuinely large payloads raise it via `QUICKJS_MEMORY_LIMIT_MB`.\n///\n/// Sizing constraint: evals are authenticated and, within a worker process, run\n/// one at a time (`transform_input` awaits each transform sequentially and each\n/// eval drops its runtime before the next), so in the default one-worker-per-\n/// process deployment the peak is a single cap. Native / multi-worker-in-process\n/// mode runs up to `NUM_WORKERS` evals concurrently in one heap, so the peak is\n/// `NUM_WORKERS × cap` — hence a modest default rather than a large one.\n#[cfg(feature = \"quickjs\")]\nconst DEFAULT_QUICKJS_MEMORY_LIMIT_BYTES: usize = 128 * 1024 * 1024;\n","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-jseval/src/lib.rs#L307-L343","documentation":"A flow step-input transform expression evaluated with QuickJS exceeded the hard wall-clock timeout (EVAL_TIMEOUT_MS). The tokio select/timed wrapper aborted the evaluation and returned this error instead of the expression result.","triggerScenarios":"An expression like `JSON.stringify(results.step)` on a very large payload, an accidental infinite loop (e.g. `while(true)` or O(n^2) mapping over a big array) inside a step-input transform, or a transform referencing a huge previous-step result that takes longer than the timeout to process.","commonSituations":"Passing megabyte-scale payloads through flow input transforms; authoring a transform with an unbounded loop; a slow string-building expression over thousands of rows.","solutions":["Reduce the amount of data the expression handles — filter/map earlier in the flow instead of inside the transform","Rewrite the expression to avoid unbounded loops and quadratic operations","Move heavy processing into a proper script step rather than a step-input transform","Raise the eval timeout via the EVAL_TIMEOUT_MS environment variable if legitimately slow but bounded"],"exampleFix":"// before\nresults.items.map(x => expensiveTransform(x))  // O(n^2), times out\n// after\nresults.items.filter(x => x.keep).map(x => expensiveTransform(x))","handlingStrategy":"try-catch","validationCode":"// bound work before submitting the expression\nif (results.items.length > 10000) throw new Error('too many items for transform');","typeGuard":null,"tryCatchPattern":"try {\n  const out = await evalExpression(expr, inputs);\n} catch (e) {\n  if (String(e).includes('took too long to execute')) {\n    // fall back to a dedicated script step instead of the transform\n  }\n  throw e;\n}","preventionTips":["Avoid unbounded loops in transform expressions","Filter large arrays before transforming","Keep transforms trivial; move heavy work into script steps","Tune EVAL_TIMEOUT_MS only when evaluations are legitimately long"],"tags":["javascript","timeout","flows"],"backgroundTag":"expression-evaluation-timeout","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}