conductor-oss/conductor · error · NonTransientException

Script execution interrupted: %s

Error message

Script execution interrupted: %s

What it means

Thrown on the context-pool path when the thread executing ScriptEvaluator.eval is itself interrupted (InterruptedException) while waiting for the Future. The code resets the thread's interrupt flag and wraps the cause message in a NonTransientException. This is an orchestration-level cancellation, not a script defect.

Source

Thrown at core/src/main/java/com/netflix/conductor/core/events/ScriptEvaluator.java:341

                Future<Value> futureResult =
                        executorService.submit(() -> finalScriptContext.getContext().eval(source));
                Value value =
                        futureResult.get(maxExecutionTimeSeconds.getSeconds(), TimeUnit.SECONDS);
                return getObject(value);
            } catch (TimeoutException e) {
                if (scriptContext != null) {
                    interrupt(scriptContext.getContext());
                }
                throw new NonTransientException(
                        String.format(
                                "Script not evaluated within %d seconds, interrupted.",
                                maxExecutionTimeSeconds.getSeconds()));
            } catch (ExecutionException ee) {
                handlePolyglotException(ee);
                return null;
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new NonTransientException("Script execution interrupted: " + ie.getMessage());
            } finally {
                if (scriptContext != null) {
                    scriptContext.clearBindings();
                    if (!contextPool.offer(scriptContext)) {
                        scriptContext.getContext().close();
                        LOGGER.warn(
                                "ScriptExecutionContext pool is full, context closed and not returned to pool.");
                    }
                }
            }
        } else {
            // No context pool - create new context for each execution
            try (Context context = createNewContext()) {
                final Value jsBindings = context.getBindings("js");
                jsBindings.putMember("$", input);
                if (console != null) {
                    jsBindings.putMember("console", console);
                }

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Confirm whether the interruption was operator-initiated (terminate workflow, shutdown) — if so, this is expected, not a bug.
  2. Check server logs for shutdown or task-cancel events around the same timestamp.
  3. If interruptions recur under load, review executor sizing and thread-pool saturation of the script executorService.
  4. Do not treat this as retryable: the same script will be interrupted again if the workflow is being torn down.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    Object result = ScriptEvaluator.eval(script, input);
} catch (NonTransientException e) {
    if (Thread.currentThread().isInterrupted()) {
        // interruption-driven; do not retry, surface to caller
    }
    handleScriptFailure(e);
}

Prevention

When it happens

Trigger: The workflow or task is cancelled/terminated by the engine, the JVM is shutting down, or an upstream caller interrupts the worker thread while a script eval is in flight on the pooled context path.

Common situations: Operator calls terminate on a running workflow whose JS task is executing; graceful shutdown interrupts in-flight evaluator threads; a parent thread pool is shutdown now.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/8d4473a1b63362eb. Report an issue: GitHub.