{"record":{"id":"7fab2369915f26f1","repo":"conductor-oss/conductor","slug":"script-not-evaluated-within-d-seconds-interrupte","errorCode":null,"errorMessage":"Script not evaluated within %d seconds, interrupted.","messagePattern":"Script not evaluated within (.+?) seconds, interrupted\\.","errorType":"exception","errorClass":"NonTransientException","httpStatus":500,"severity":"error","filePath":"core/src/main/java/com/netflix/conductor/core/events/ScriptEvaluator.java","lineNumber":332,"sourceCode":"        final Source source = getSource(script);\n\n        if (contextPoolEnabled) {\n            // Context pool implementation\n            ScriptExecutionContext scriptContext = null;\n            try {\n                scriptContext = contextPool.take();\n                final ScriptExecutionContext finalScriptContext = scriptContext;\n                finalScriptContext.prepareBindings(input, console);\n                Future<Value> futureResult =\n                        executorService.submit(() -> finalScriptContext.getContext().eval(source));\n                Value value =\n                        futureResult.get(maxExecutionTimeSeconds.getSeconds(), TimeUnit.SECONDS);\n                return getObject(value);\n            } catch (TimeoutException e) {\n                if (scriptContext != null) {\n                    interrupt(scriptContext.getContext());\n                }\n                throw new NonTransientException(\n                        String.format(\n                                \"Script not evaluated within %d seconds, interrupted.\",\n                                maxExecutionTimeSeconds.getSeconds()));\n            } catch (ExecutionException ee) {\n                handlePolyglotException(ee);\n                return null;\n            } catch (InterruptedException ie) {\n                Thread.currentThread().interrupt();\n                throw new NonTransientException(\"Script execution interrupted: \" + ie.getMessage());\n            } finally {\n                if (scriptContext != null) {\n                    scriptContext.clearBindings();\n                    if (!contextPool.offer(scriptContext)) {\n                        scriptContext.getContext().close();\n                        LOGGER.warn(\n                                \"ScriptExecutionContext pool is full, context closed and not returned to pool.\");\n                    }\n                }","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/com/netflix/conductor/core/events/ScriptEvaluator.java#L314-L350","documentation":"Thrown by ScriptEvaluator when a GraalVM JavaScript expression does not finish within maxExecutionTimeSeconds (default 4s) on the context-pool code path (CONDUCTOR_SCRIPT_CONTEXT_POOL_ENABLED=true). The evaluator submits the eval to an executor and calls Future.get with the timeout; a TimeoutException is caught, the polyglot Context is interrupted, and a NonTransientException is raised. NonTransient tells the workflow engine that retrying the same script will not help, so the task is not retried automatically.","triggerScenarios":"Calling ScriptEvaluator.eval(script, input) (directly or via an inline JavascriptTask / expression evaluator) with a script containing an infinite loop, a very heavy computation, or a blocking call that exceeds the configured maxExecutionTimeSeconds. Only fires when the context pool is enabled.","commonSituations":"A workflow uses a JavaScript expression task with `while(true){}` or unbounded recursion; an input-driven script whose size grew past the 4s budget under load; maxExecutionTimeSeconds left at the 4s default while scripts legitimately need longer; context pool enabled to reuse contexts but a script regresses on latency.","solutions":["Inspect the failing script for loops/recursion/blocking calls and bound it algorithmically.","Raise the budget via `conductor.systemTaskEvalTimeoutSeconds` (or the ScriptEvaluator initializer maxSeconds arg) only if the script is genuinely O(n) over large input.","Refactor the logic out of inline JS into a dedicated worker task for long-running computation.","Keep the context pool disabled (the default) unless you fully control every script, since pooled contexts can change latency characteristics.","Catch NonTransientException at the task boundary and fail the task explicitly with a clear reason instead of relying on the generic message."],"exampleFix":"// before\nvar i = 0; while (true) { i++; }  // unbounded\n\n// after\nvar i = 0, max = 1_000_000;\nwhile (i < max) { i++; }  // bounded","handlingStrategy":"validation","validationCode":"// Before exposing a script, sanity-check it does not contain obvious infinite loops.\n// Pre-flight: run it offline with the same maxExecutionTimeSeconds budget.\nDuration budget = Duration.ofSeconds(4);\nlong start = System.nanoTime();\nObject r = runInSandboxWithTimeout(script, input, budget); // your harness\nlong elapsed = (System.nanoTime() - start) / 1_000_000L;\nif (elapsed >= budget.toMillis() * 0.8) {\n    LOGGER.warn(\"Script near timeout budget ({}ms / {}ms); consider refactoring\", elapsed, budget.toMillis());\n}","typeGuard":null,"tryCatchPattern":"// NonTransientException is not retriable; fail the task cleanly.\ntry {\n    Object result = ScriptEvaluator.eval(script, input);\n} catch (NonTransientException e) {\n    // record reason, mark task FAILED, do NOT retry\n    task.setReasonForIncompletion(e.getMessage());\n    task.setStatus(TaskModel.Status.FAILED);\n}","preventionTips":["Cap all loops in inline JS with an explicit iteration bound.","Keep the default 4s budget unless scripts are proven to need more.","Run new scripts in a local GraalJS harness with the same timeout before deploying.","Avoid blocking/host calls — the engine disables load/print/console/host access by design."],"tags":["conductor","graalvm","javascript","script-evaluation","timeout","non-transient"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}