elastic/elasticsearch · error · IllegalStateException

MockApmServer not started

Error message

MockApmServer not started

What it means

Thrown by MockApmServer.getPort() when the 'instance' field (the HttpServer) is null — i.e. getPort() was called before start() bound the HTTP server, or after stop() nulled it. The method has no fallback: it needs the live HttpServer's bound port.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/MockApmServer.java:117

     */
    public void start() throws IOException {
        if (instance != null) {
            throw new IllegalStateException("MockApmServer already started");
        }
        InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
        HttpServer server = HttpServer.create(addr, 10);
        server.createContext("/", new RootHandler());
        server.start();
        instance = server;
        logger.lifecycle("MockApmServer started on port " + server.getAddress().getPort());

        grpcInstance = ServerBuilder.forPort(0).addService(new GrpcMetricsService()).addService(new GrpcTraceService()).build().start();
        logger.lifecycle("MockApmServer gRPC (OTLP metrics + traces) started on port " + grpcInstance.getPort());
    }

    public int getPort() {
        if (instance == null) {
            throw new IllegalStateException("MockApmServer not started");
        }
        return instance.getAddress().getPort();
    }

    public int getGrpcPort() {
        if (grpcInstance == null) {
            throw new IllegalStateException("MockApmServer not started");
        }
        return grpcInstance.getPort();
    }

    /**
     * Stop the server gracefully if possible
     */
    public void stop() {
        if (instance != null) {
            logger.lifecycle("stopping apm server");
            instance.stop(1);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure start() completes before any getPort() call — sequence them explicitly.
  2. After stop(), do not call getPort(); create a new MockApmServer and start() it first.
  3. If unsure of state, add a guard: 'if (mockServer != null && mockServer.isStarted()) mockServer.getPort()'.

Example fix

// before:
mockServer.start();
int p = mockServer.getPort();  // ok only if start succeeded
// guard:
if (mockServer != null) {
    mockServer.start();
    int p = mockServer.getPort();
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (instance == null) {
    throw new IllegalStateException("Call start() before getPort()");
}

Type guard

boolean httpStarted(MockApmServer s) { return s != null && s.instanceFieldNotNull(); } // conceptual — instance is private; expose isStarted()

Prevention

When it happens

Trigger: Calling mockServer.getPort() before mockServer.start(), or after stop() set instance=null. The HttpServer only has a concrete port after server.start() binds to 0.0.0.0:0.

Common situations: Test code or a build hook that queries the APM port before the RunTask has started the mock; reusing the MockApmServer across a stop/start cycle without re-initialising.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/ec2e7abe5d55157e. Report an issue: GitHub.