quarkusio/quarkus · error · IllegalStateException

The application has not been started

Error message

The application has not been started

What it means

Application.stop() enforces a proper lifecycle: if stop is called while the instance is still in ST_INITIAL (never started), there is nothing to shut down and it throws this IllegalStateException. It is a misuse guard — the stop/awaitStart machinery assumes start() was invoked (or is in progress) on the instance.

Source

Thrown at core/runtime/src/main/java/io/quarkus/runtime/Application.java:186

    /**
     * Stop the application. If another thread is also trying to stop the application, this method waits for that
     * thread to finish. Returns immediately if the application is already stopped. If an exception is thrown during
     * stop, that exception is propagated.
     */
    public final void stop(Runnable afterStopTask) {
        Logger logger = Logger.getLogger(Application.class);
        logger.debugf("Stopping application");
        if (logger.isTraceEnabled()) {
            logger.tracef(new RuntimeException("Application Stop Stack Trace"), "Application shutting down");
        }
        final Lock stateLock = this.stateLock;
        stateLock.lock();
        try {
            loop: for (;;)
                switch (state) {
                    case ST_INITIAL:
                        throw new IllegalStateException("The application has not been started");
                    case ST_STARTING: {
                        try {
                            stateCond.await();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            throw interruptedOnAwaitStart();
                        }
                        break;
                    }
                    case ST_STARTED:
                        break loop; // normal shutdown
                    case ST_STOPPING: {
                        try {
                            stateCond.await();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            throw interruptedOnAwaitStop();
                        }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Only call stop() on instances that were successfully started; guard cleanup with a started flag or check ApplicationLifecycleManager state.
  2. Use try/finally or the framework's lifecycle API so stop is invoked exactly once per started instance.
  3. If start() failed, inspect and fix the startup exception first; stop() on a never-started instance is not the recovery path.
  4. In tests, use QuarkusTest/test-extension utilities that manage lifecycle instead of manual start/stop.

Example fix

// before
Application app = new Application();
app.stop(); // IllegalStateException: The application has not been started
// after
Application app = new Application();
ApplicationLifecycleManager.run(app, null, null, LaunchMode.NORMAL);
try {
    // use app
} finally {
    app.stop();
}
Defensive patterns

Strategy: validation

Validate before calling

boolean started = app.isStarted(); // or track your own flag set after start() returns
if (!started) {
    throw new IllegalStateException("Cannot stop: application was never started");
}

Type guard

boolean canStop(Application app) {
    try {
        java.lang.reflect.Field f = Application.class.getDeclaredField("state");
        f.setAccessible(true);
        return ((AtomicInteger) f.get(app)).get() != 0; // != ST_INITIAL
    } catch (ReflectiveOperationException e) {
        return false;
    }
}

Try / catch

try {
    app.stop();
} catch (IllegalStateException e) {
    if ("The application has not been started".equals(e.getMessage())) {
        log.debug("stop() skipped: never started");
    } else throw e;
}

Prevention

When it happens

Trigger: Calling app.stop() on an Application instance that was constructed but never started, or after start() failed so early that the state never advanced past ST_INITIAL — the switch case ST_INITIAL throws immediately.

Common situations: JUnit tests cleaning up in @AfterEach without checking whether start succeeded; error-handling paths calling stop() after a failed bootstrap; double-cleanup logic that stops unstarted instances.

Related errors


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