{"record":{"id":"1a20e3c1289a6c93","repo":"karatelabs/karate","slug":"settimeout","errorCode":null,"errorMessage":"setTimeout: ","messagePattern":"setTimeout: ","errorType":"exception","errorClass":"EngineInterruptedException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/AsyncSupport.java","lineNumber":782,"sourceCode":"            retireTimer(record);\n            throw new EngineInterruptedException(\"setTimeout: karate is shutting down\");\n        }\n        ScheduledFuture<?> future;\n        try {\n            future = timer.schedule(() -> {\n                // foreign thread: may only win the CAS and publish, never run JS\n                if (record.fire()) {\n                    forgetTimer(record);\n                    scope.removeTimer(id);\n                    scope.publishSuccessor(record.token, AsyncJob.one(new AsyncJob.Timer(id, target, extra)));\n                }\n            }, delay);\n        } catch (RuntimeException e) {\n            // the scheduler was stopped concurrently (RejectedExecutionException):\n            // unwind the record and its token, or nothing ever releases them\n            scope.removeTimer(id);\n            retireTimer(record);\n            throw new EngineInterruptedException(\"setTimeout: \" + e);\n        }\n        record.future = future;\n        if (!record.isLive()) {\n            // retired between the arm and the assignment — the future is ours to drop\n            future.cancel(false);\n        }\n        return id;\n    }\n\n    static Object clearTimeout(Context context, Object[] args) {\n        Engine engine = context == null ? null : context.getEngine();\n        AsyncScope scope = engine == null ? null : engine.currentScope();\n        if (scope == null) {\n            return Terms.UNDEFINED;\n        }\n        Object id = arg(args, 0);\n        Number n = id instanceof Number number ? number : Terms.objectToNumber(id);\n        if (n == null || Double.isNaN(n.doubleValue())) {","sourceCodeStart":764,"sourceCodeEnd":800,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/AsyncSupport.java#L764-L800","documentation":"The TimerScheduler threw a RuntimeException (typically RejectedExecutionException) when scheduling the timer's callback, meaning the scheduler's executor was stopped concurrently. setTimeout unwinds the timer record and its AsyncToken and wraps the cause in EngineInterruptedException so nothing leaks.","triggerScenarios":"setTimeout's timer.schedule() call lands after the scheduler's underlying executor has been shut down; any RuntimeException from the scheduling call is rethrown wrapped as 'setTimeout: <cause>'.","commonSituations":"RejectedExecutionException during engine teardown; executor shutdown racing timer creation from another thread; calling setTimeout from a hook that runs after the runner's executor is closed.","solutions":["Check the wrapped cause (e.g. RejectedExecutionException) to confirm the executor was stopped, and stop scheduling at that point in your code","Catch EngineInterruptedException and treat it as a benign shutdown signal","Move timer scheduling earlier in the scenario lifecycle","Ensure only the framework shuts the executor down, and never schedule from post-shutdown hooks"],"exampleFix":"// before\nsetTimeout(() => run(), 10); // RuntimeException: scheduler stopped\n// after\ntry {\n  setTimeout(() => run(), 10);\n} catch (e) {\n  if (!String(e).includes('RejectedExecutionException')) throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  setTimeout(fn, delay);\n} catch (e) {\n  if (String(e).includes('RejectedExecutionException')) { /* scheduler stopped */ }\n  else throw e;\n}","preventionTips":["Schedule timers only while the runner's executor is alive","Centralize timer creation in framework-owned code","Unwind timer records promptly on shutdown"],"tags":["javascript","async","timer","executor","shutdown"],"backgroundTag":"thread-interrupted","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}