{"record":{"id":"f6d875f962ff6bfe","repo":"stanfordnlp/CoreNLP","slug":"could-not-ensure-a-server","errorCode":null,"errorMessage":"Could not ensure a server:","messagePattern":"Could not ensure a server:","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"src/edu/stanford/nlp/pipeline/WebServiceAnnotator.java","lineNumber":385,"sourceCode":"\n        // 3B. We've failed to annotate, but should maybe retry\n        // 3B.1. Stop the server, if this is our third try\n        synchronized (this) {\n          if (tries >= 2 && this.server.isPresent()) {\n            this.server.get().kill();\n            this.server = Optional.empty();\n          }\n        }\n        // 3B.2. Retry\n        if (tries < 3) {\n          annotate(annotation, tries + 1);\n        } else {\n          throw new RuntimeException(\"Could not annotate document after 3 tries:\", e);\n        }\n\n      }\n    } catch (TimeoutException | IOException e) {\n      throw new RuntimeException(\"Could not ensure a server:\", e);\n    }\n  }\n\n\n  /**\n   * A quick script to debug server lifecycle.\n   */\n  public static void main(String[] args) throws InterruptedException {\n    WebServiceAnnotator annotator = new WebServiceAnnotator(){\n\n      @Override\n      public Set<Class<? extends CoreAnnotation>> requirementsSatisfied() {\n        return Collections.emptySet();\n      }\n\n      @Override\n      public Set<Class<? extends CoreAnnotation>> requires() {\n        return Collections.emptySet();","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/pipeline/WebServiceAnnotator.java#L367-L403","documentation":"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.","triggerScenarios":"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:\".","commonSituations":"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.","solutions":["Inspect the chained cause (e.getCause()) to find whether it was a timeout or a connection failure","Verify the server is running: curl the server's ping/health endpoint at the configured host:port","Check the annotator's server URL/port configuration properties against the actual server address","Increase the connection/annotation timeout setting if the server is slow to start or respond","Start the CoreNLP server before the client, and add a readiness wait/retry loop"],"exampleFix":"// before\nnew WebServiceAnnotator(); // default URL, server never started\n// after\nProperties props = new Properties();\nprops.setProperty(\"annotators\", \"wss\");\nprops.setProperty(\"webservice.endpoint\", \"http://localhost:9000\"); // reachable server\n// ensure the server is up first:\nProcess server = new ProcessBuilder(\"java\", \"-mx4g\", \"-cp\", \"*\",\n    \"edu.stanford.nlp.pipeline.StanfordCoreNLPServer\", \"-port\", \"9000\").start();\nwaitUntilReady(\"http://localhost:9000\", Duration.ofSeconds(60));","handlingStrategy":"try-catch","validationCode":"boolean ready = false;\ntry {\n  HttpURLConnection c = (HttpURLConnection) new URL(serverUrl + \"/ping\").openConnection();\n  c.setConnectTimeout(2000);\n  ready = c.getResponseCode() == 200;\n} catch (IOException ignored) {}\nif (!ready) throw new IllegalStateException(\"Annotation server not reachable at \" + serverUrl);","typeGuard":null,"tryCatchPattern":"try {\n  annotator.annotate(annotation);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Could not ensure a server\")) {\n    Throwable cause = e.getCause(); // TimeoutException => raise timeout; IOException => check server/URL\n    throw new ServerUnavailableException(serverUrl, cause);\n  }\n  throw e;\n}","preventionTips":["Start the CoreNLP server and poll its health endpoint before annotating","Externalize the server URL/port into configuration and validate at startup","Set a generous but bounded timeout suited to first-request server warm-up","Log e.getCause() — the wrapped TimeoutException vs IOException distinguishes slow server vs unreachable host"],"tags":["network","http","server-lifecycle","timeout","runtime-exception"],"backgroundTag":"connection-refused","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}