quarkusio/quarkus · error

Thread not suspended

Error message

Thread not suspended

What it means

RemoteThread.evaluateInRenderThread() executes an evaluation on a paused render thread, so it requires state == SUSPENDED. It throws IllegalStateException('Thread not suspended') when the render thread is still running (or otherwise not suspended), because evaluating expressions against a running render would race with template rendering.

Source

Thrown at independent-projects/qute/debug/src/main/java/io/quarkus/qute/debug/agent/RemoteThread.java:362

     *
     * <p>
     * <b>Threading model:</b><br>
     * This method must be called from the debugger control thread (not the render thread itself).
     * The provided callable will be executed synchronously within the render thread context, ensuring
     * compatibility with request-bound state.
     * </p>
     *
     * @param action the task to execute within the render thread context.
     *        It should return a {@link CompletableFuture} representing the computation result.
     * @return a {@link CompletableFuture} containing the result of the executed task
     * @throws IllegalStateException if the thread is not currently suspended or if another
     *         evaluation task is already pending
     */
    public CompletableFuture<Object> evaluateInRenderThread(Callable<CompletableFuture<Object>> action) {
        synchronized (lock) {
            // Ensure the render thread is suspended before executing any task
            if (this.state != DebuggerState.SUSPENDED) {
                throw new IllegalStateException("Thread not suspended");
            }

            // Prevent concurrent evaluation tasks from overlapping
            if (pendingTask != null) {
                throw new IllegalStateException("A task is already pending");
            }

            // Schedule the evaluation task to be executed by the render thread
            pendingTask = action;
            taskResult = null;

            // Wake up the suspended render thread so it can pick up and execute the task
            lock.notifyAll();

            // Wait for the render thread to process and complete the pending task
            boolean intr = false;
            try {
                while (pendingTask != null) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Only call evaluateInRenderThread() after the thread reports SUSPENDED (e.g. after a breakpoint or pause completes).
  2. Await the CompletableFuture from pause()/breakpoint suspension before evaluating.
  3. Catch IllegalStateException and retry once the suspended event arrives.
  4. In DAP clients, gate evaluate requests on the 'stopped' event for that thread.

Example fix

// before
Object val = thread.evaluateInRenderThread(action).get();
// after
if (thread.getState() == DebuggerState.SUSPENDED) {
    Object val = thread.evaluateInRenderThread(action).get();
} else {
    // wait for suspension event first
}
Defensive patterns

Strategy: validation

Validate before calling

if (thread.getState() != DebuggerState.SUSPENDED) {
    throw new IllegalStateException("Wait for suspension before evaluating");
}
Object v = thread.evaluateInRenderThread(action).get();

Type guard

boolean canEvaluate(RemoteThread t) {
    return t.getState() == DebuggerState.SUSPENDED;
}

Try / catch

try {
    return thread.evaluateInRenderThread(action).get();
} catch (IllegalStateException e) {
    if ("Thread not suspended".equals(e.getMessage())) {
        // wait for suspension event, then retry once
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling evaluateInRenderThread() while the render thread is RUNNING — e.g. a DAP evaluate request issued without waiting for the thread to hit a breakpoint/suspension, or after the thread resumed.

Common situations: Debug clients sending evaluateRequests immediately after attach; evaluate calls racing with a continue; tests invoking evaluation before triggering a suspension.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/8f2f8106591fe80f. Report an issue: GitHub.