apache/shardingsphere · critical · IllegalStateException

Backend executor engine is unavailable in `%s` lifecycle sta

Error message

Backend executor engine is unavailable in `%s` lifecycle state.

What it means

IllegalStateException thrown by BackendExecutorContext.getExecutorEngine() when the executor engine field is still null and the context lifecycle state is CLOSED. After shutdown() sets lifecycleState = CLOSED, any request-side lookup of the executor engine is rejected until an explicit re-initialization; this branch is the pre-init CLOSED check (line 68). It signals the proxy backend is being used after it was shut down.

Source

Thrown at proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/context/BackendExecutorContext.java:68

     * It may explicitly restore the context from the closed state for repeated proxy lifecycles in the same JVM.</p>
     */
    public synchronized void init() {
        closeExecutorEngine();
        executorEngine = ExecutorEngine.createExecutorEngineWithSize(
                ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getProps().<Integer>getValue(ConfigurationPropertyKey.KERNEL_EXECUTOR_SIZE));
        lifecycleState = LifecycleState.RUNNING;
    }
    
    /**
     * Get executor engine.
     *
     * @return executor engine
     * @throws IllegalStateException backend executor is unavailable in current lifecycle state
     */
    public synchronized ExecutorEngine getExecutorEngine() {
        if (null == executorEngine) {
            if (LifecycleState.CLOSED == lifecycleState) {
                throw new IllegalStateException(String.format("Backend executor engine is unavailable in `%s` lifecycle state.", lifecycleState));
            }
            init();
        }
        if (LifecycleState.RUNNING != lifecycleState) {
            throw new IllegalStateException(String.format("Backend executor engine is unavailable in `%s` lifecycle state.", lifecycleState));
        }
        return executorEngine;
    }
    
    /**
     * Shutdown backend executor context.
     *
     * <p>After shutdown, request-side executor lookup is rejected until the next explicit lifecycle initialization.</p>
     */
    public synchronized void shutdown() {
        closeExecutorEngine();
        lifecycleState = LifecycleState.CLOSED;
    }

View on GitHub (pinned to e952770a21)

Solutions

  1. Ensure no query/execution path runs after ProxyContext/BackendExecutorContext shutdown; drain in-flight requests before shutting down
  2. If the proxy is intentionally restarted in-process, call the lifecycle init path again before issuing queries (getExecutorEngine re-inits only when state is not CLOSED)
  3. In tests, reset or re-initialize BackendExecutorContext between test cases instead of using it after shutdown()

Example fix

// before
BackendExecutorContext.getInstance().shutdown();
ExecutorEngine engine = BackendExecutorContext.getInstance().getExecutorEngine(); // IllegalStateException

// after
BackendExecutorContext.getInstance().shutdown();
// restart lifecycle before next use
BackendExecutorContext.getInstance().init();
ExecutorEngine engine = BackendExecutorContext.getInstance().getExecutorEngine();
Defensive patterns

Strategy: validation

Try / catch

try {
    ExecutorEngine engine = BackendExecutorContext.getInstance().getExecutorEngine();
} catch (final IllegalStateException ex) {
    // context is CLOSED: do not retry; re-init lifecycle or fail the request fast
    throw new ServiceUnavailableException("Proxy executor is shut down", ex);
}

Prevention

When it happens

Trigger: Calling BackendExecutorContext.getInstance().getExecutorEngine() after BackendExecutorContext.shutdown() has run (proxy graceful shutdown, XA/dist transaction driver reload, or a test that shuts down the context then issues a query). The null executorEngine + LifecycleState.CLOSED combination hits the first throw.

Common situations: Shutdown hooks racing in-flight queries during proxy stop/restart; unit tests that call shutdown() in @AfterEach but reuse the singleton context afterwards; embedded proxy restarted inside the same JVM without re-running init().

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/e413289d0dbfc742. Report an issue: GitHub.