apache/pulsar · error · PulsarServerException

javaInstanceRunnable is not initialized

Error message

javaInstanceRunnable is not initialized

What it means

ThreadRuntime.getPrometheusMetrics() returns the Java instance's stats as a Prometheus string, but this only works after the instance runnable has been created/started. If javaInstanceRunnable is still null (getPrometheusMetrics called before the thread instance finished initializing), it throws PulsarServerException('javaInstanceRunnable is not initialized').

Source

Thrown at pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/thread/ThreadRuntime.java:311

        statsFuture.complete(functionStatus);
        return statsFuture;
    }

    @Override
    public CompletableFuture<MetricsData> getAndResetMetrics() {
        return CompletableFuture.completedFuture(javaInstanceRunnable.getAndResetMetrics());
    }


    @Override
    public CompletableFuture<MetricsData> getMetrics(int instanceId) {
        return CompletableFuture.completedFuture(javaInstanceRunnable.getMetrics());
    }

    @Override
    public String getPrometheusMetrics() throws IOException {
        if (javaInstanceRunnable == null) {
            throw new PulsarServerException("javaInstanceRunnable is not initialized");
        }
        return javaInstanceRunnable.getStatsAsString();
    }

    @Override
    public CompletableFuture<Void> resetMetrics() {
        javaInstanceRunnable.resetMetrics();
        return CompletableFuture.completedFuture(null);
    }

    @Override
    public boolean isAlive() {
        if (this.fnThread != null) {
            return this.fnThread.isAlive();
        } else {
            return false;
        }
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Ensure the function instance has fully started before scraping its Prometheus metrics (retry the metrics call after startup completes).
  2. Investigate why initialization never created javaInstanceRunnable (check earlier instance startup errors in the worker log).
  3. Handle PulsarServerException from the metrics endpoint and treat it as retryable/until-ready.
  4. In code, guard calls so getPrometheusMetrics is only invoked on a started ThreadRuntime.

Example fix

// before
String metrics = threadRuntime.getPrometheusMetrics();
// after
try {
    String metrics = threadRuntime.getPrometheusMetrics();
} catch (PulsarServerException e) {
    // instance not started yet; retry after startup or skip this scrape
}
Defensive patterns

Strategy: try-catch

Validate before calling

// only call after the instance has started; expose/check a started flag if you own the lifecycle
if (!instanceStarted) {
    throw new IllegalStateException("call getPrometheusMetrics only after ThreadRuntime.start() completed");
}

Try / catch

try {
    String metrics = threadRuntime.getPrometheusMetrics();
} catch (PulsarServerException e) {
    if (e.getMessage() != null && e.getMessage().contains("javaInstanceRunnable is not initialized")) {
        // instance not started yet: retry after startup or skip this scrape
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling getPrometheusMetrics() (e.g. via the worker's metrics/promise endpoint) on a ThreadRuntime whose start() has not yet constructed javaInstanceRunnable, or after initialization failed before runnable creation.

Common situations: Metrics scrapers hitting the function worker immediately after function assignment, racing instance startup; function instance failed to initialize leaving the runtime half-constructed; tests or tooling invoking getPrometheusMetrics() on a freshly created ThreadRuntime.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/9fc3be0cac7a2732. Report an issue: GitHub.