languagetool-org/languagetool · error · TimeoutException

${e.getMessage()}

Error message

${e.getMessage()}

What it means

RemoteLanguageModel.batchScore calls a gRPC BERT scoring service; on StatusRuntimeException the method converts DEADLINE_EXCEEDED into a TimeoutException carrying the original message. Any other status (UNAVAILABLE, PERMISSION_DENIED, etc.) is rethrown unchanged. So this message is the raw gRPC status message, surfaced when the remote scorer fails or times out.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/languagemodel/bert/RemoteLanguageModel.java:154

    }
    BatchScoreRequest batch = BatchScoreRequest.newBuilder().addAllRequests(
      uncachedRequests.stream().map(Request::convert).collect(Collectors.toList())
    ).build();
    // TODO multiple masks
    List<List<Double>> nonCacheResult;
    try {
      BertLmBlockingStub stub;
      if (timeoutMilliseconds > 0) {
        stub = model.withDeadlineAfter(timeoutMilliseconds, TimeUnit.MILLISECONDS);
      } else {
        stub = model;
      }
      nonCacheResult = stub.batchScore(batch)
        .getResponsesList().stream().map(r ->
          r.getScoresList().get(0).getScoreList()).collect(Collectors.toList());
    } catch (StatusRuntimeException e) {
      if (e.getStatus().getCode() == Status.DEADLINE_EXCEEDED.getCode()) {
        throw new TimeoutException(e.getMessage());
      } else {
        throw e;
      }
    }
    //
    List<List<Double>> allResults = new ArrayList<>();
    int i = 0;
    for (Request request : requests) {
      List<Double> result = cachedRequests.get(request);
      if (result != null) {
        //System.out.println("Adding result from cache");
        allResults.add(result);
      } else {
        //System.out.println("Adding result from remote");
        allResults.add(nonCacheResult.get(i++));
      }
    }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Check the remote BERT scorer is running and the configured host/port is correct.
  2. Increase the gRPC deadline for large batches or slow networks.
  3. Reduce batch size to lower per-call latency below the deadline.
  4. Inspect the wrapped/rethrown message for the actual gRPC status (UNAVAILABLE, DEADLINE_EXCEEDED) and address it (network, auth, server health).
  5. Add client-side retry with backoff for transient UNAVAILABLE statuses.

Example fix

// before
stub = RemoteLanguageModelProtocolServiceGrpc.newBlockingStub(channel);
List<List<Double>> r = model.batchScore(batch);
// after: smaller batch + longer deadline
stub = RemoteLanguageModelProtocolServiceGrpc.newBlockingStub(channel)
    .withDeadlineAfter(120, TimeUnit.SECONDS);
List<List<Double>> r = model.batchScore(smallerBatch);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!isServerReachable(host, port))
  throw new IllegalStateException("BERT scorer not reachable at " + host + ":" + port);

Try / catch

try {
  results = model.batchScore(batch);
} catch (TimeoutException e) {
  // retry with smaller batch / longer deadline
} catch (StatusRuntimeException e) {
  // check e.getStatus().getCode(); alert on UNAVAILABLE
}

Prevention

When it happens

Trigger: Calling batchScore() when the remote gRPC service is unreachable, overloaded, slow (exceeding the deadline), or rejects the call; the stub throws StatusRuntimeException which is either wrapped as TimeoutException or rethrown with its message.

Common situations: BERT scoring server not running or on wrong host/port, network latency causing the gRPC deadline to expire, server crash mid-request, TLS/auth failure to the scorer service.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/30f55739b2e7a4c9. Report an issue: GitHub.