stanfordnlp/CoreNLP · critical · RuntimeException

Could not ensure a server:

Error message

Could not ensure a server:

What it means

WebServiceAnnotator wraps any TimeoutException or IOException encountered while checking/starting its annotation server into a RuntimeException with the generic message "Could not ensure a server:". It is thrown from the annotate() path when the annotator cannot guarantee a reachable backend server before annotating a document. The original exception is chained as the cause, so the real reason (startup failure, timeout, connection problem) is always in the cause.

Solutions

  1. Inspect the chained cause (e.getCause()) to find whether it was a timeout or a connection failure
  2. Verify the server is running: curl the server's ping/health endpoint at the configured host:port
  3. Check the annotator's server URL/port configuration properties against the actual server address
  4. Increase the connection/annotation timeout setting if the server is slow to start or respond
  5. Start the CoreNLP server before the client, and add a readiness wait/retry loop

Example fix

// before
new WebServiceAnnotator(); // default URL, server never started
// after
Properties props = new Properties();
props.setProperty("annotators", "wss");
props.setProperty("webservice.endpoint", "http://localhost:9000"); // reachable server
// ensure the server is up first:
Process server = new ProcessBuilder("java", "-mx4g", "-cp", "*",
    "edu.stanford.nlp.pipeline.StanfordCoreNLPServer", "-port", "9000").start();
waitUntilReady("http://localhost:9000", Duration.ofSeconds(60));
Defensive patterns

Strategy: try-catch

Validate before calling

boolean ready = false;
try {
  HttpURLConnection c = (HttpURLConnection) new URL(serverUrl + "/ping").openConnection();
  c.setConnectTimeout(2000);
  ready = c.getResponseCode() == 200;
} catch (IOException ignored) {}
if (!ready) throw new IllegalStateException("Annotation server not reachable at " + serverUrl);

Try / catch

try {
  annotator.annotate(annotation);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Could not ensure a server")) {
    Throwable cause = e.getCause(); // TimeoutException => raise timeout; IOException => check server/URL
    throw new ServerUnavailableException(serverUrl, cause);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling annotate() (directly or via a StanfordCoreNLP pipeline using the webservice annotator) when the remote server does not respond before the timeout, or the HTTP/IO connection to it fails during the ensure-server step, after up to 3 annotation retries also fail with "Could not annotate document after 3 tries:".

Common situations: Server URL/port misconfigured; the Stanford CoreNLP server is not running or crashed; network/firewall blocking the port; server startup slower than the configured timeout; Docker/K8s service not yet ready.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/f6d875f962ff6bfe. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/WebServiceAnnotator.java:385

        // 3B. We've failed to annotate, but should maybe retry
        // 3B.1. Stop the server, if this is our third try
        synchronized (this) {
          if (tries >= 2 && this.server.isPresent()) {
            this.server.get().kill();
            this.server = Optional.empty();
          }
        }
        // 3B.2. Retry
        if (tries < 3) {
          annotate(annotation, tries + 1);
        } else {
          throw new RuntimeException("Could not annotate document after 3 tries:", e);
        }

      }
    } catch (TimeoutException | IOException e) {
      throw new RuntimeException("Could not ensure a server:", e);
    }
  }


  /**
   * A quick script to debug server lifecycle.
   */
  public static void main(String[] args) throws InterruptedException {
    WebServiceAnnotator annotator = new WebServiceAnnotator(){

      @Override
      public Set<Class<? extends CoreAnnotation>> requirementsSatisfied() {
        return Collections.emptySet();
      }

      @Override
      public Set<Class<? extends CoreAnnotation>> requires() {
        return Collections.emptySet();

View on GitHub (pinned to 1b7edd19c4)