junit-team/junit5 · error · JUnitException
Scheduled executor could not be stopped in an orderly manner
Error message
Scheduled executor could not be stopped in an orderly manner
What it means
Thrown by TimeoutInvocationFactory.ExecutorResource.close() when the internal 'junit-jupiter-timeout-watcher' single-thread ScheduledExecutorService does not terminate within 5 seconds of calling shutdown(). After the grace period, shutdownNow() is called and this JUnitException is raised. This executor is used for same-thread timeout enforcement (ThreadMode.SAME_THREAD) to schedule the timeout watcher task.
Source
Thrown at junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java:71
abstract static class ExecutorResource implements Store.CloseableResource, AutoCloseable {
private final ScheduledExecutorService executor;
ExecutorResource(ScheduledExecutorService executor) {
this.executor = executor;
}
ScheduledExecutorService get() {
return executor;
}
@Override
public void close() throws Exception {
executor.shutdown();
boolean terminated = executor.awaitTermination(5, TimeUnit.SECONDS);
if (!terminated) {
executor.shutdownNow();
throw new JUnitException("Scheduled executor could not be stopped in an orderly manner");
}
}
}
@SuppressWarnings("try")
static class SingleThreadExecutorResource extends ExecutorResource {
@SuppressWarnings({ "unused", "ThreadPriorityCheck" })
SingleThreadExecutorResource() {
super(Executors.newSingleThreadScheduledExecutor(runnable -> {
Thread thread = new Thread(runnable, "junit-jupiter-timeout-watcher");
thread.setPriority(Thread.MAX_PRIORITY);
return thread;
}));
}
}
}View on GitHub (pinned to 956246301e)
Solutions
- Rerun the test in isolation to rule out transient CI load
- Use ThreadMode.SEPARATE_THREAD (@Timeout(threadMode = ThreadMode.SEPARATE_THREAD)) which does not use this same-thread executor
- Ensure the test JVM has adequate CPU/memory resources
- Check for tests that hang in uninterruptible blocking operations (e.g., native I/O, infinite loops)
Defensive patterns
Strategy: try-catch
Try / catch
// This error occurs during context teardown, not in user code. // Mitigate by using SEPARATE_THREAD mode to avoid the same-thread executor: @Timeout(value = 5, unit = TimeUnit.SECONDS, threadMode = ThreadMode.SEPARATE_THREAD)
Prevention
- Use @Timeout(threadMode = ThreadMode.SEPARATE_THREAD) to avoid the same-thread executor entirely
- Ensure CI environments have adequate CPU/memory for the JVM
- Avoid tests that hang in uninterruptible blocking operations
- Rerun flaky tests to distinguish transient CI load from persistent issues
When it happens
Trigger: The executor's scheduled task (the timeout watcher) does not complete within 5 seconds of JUnit shutting down the test context. This can happen if the JVM is under heavy load, if the watched thread is stuck in an uninterruptible operation, or if the test harness is being forcefully torn down.
Common situations: Running in a heavily loaded CI environment, a test that hangs in a way that blocks the watcher thread, OOM or resource exhaustion during teardown, or running on a very slow/containerized machine where thread scheduling is delayed beyond 5 seconds.
Related errors
- Could not map TimeUnit <unit> to ChronoUnit
- Timeout duration is not in the expected format (<number> [ns
- thread mode must not be INFERRED
AI-assisted analysis of junit-team/junit5@956246301e (2026-08-04).
Data as JSON: /data/errors/7ab6a6940b4c62ed.json.
Report an issue: GitHub.