{"record":{"id":"30f55739b2e7a4c9","repo":"languagetool-org/languagetool","slug":"e-getmessage","errorCode":null,"errorMessage":"${e.getMessage()}","messagePattern":"\\$\\{e\\.getMessage\\(\\)\\}","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/languagemodel/bert/RemoteLanguageModel.java","lineNumber":154,"sourceCode":"    }\n    BatchScoreRequest batch = BatchScoreRequest.newBuilder().addAllRequests(\n      uncachedRequests.stream().map(Request::convert).collect(Collectors.toList())\n    ).build();\n    // TODO multiple masks\n    List<List<Double>> nonCacheResult;\n    try {\n      BertLmBlockingStub stub;\n      if (timeoutMilliseconds > 0) {\n        stub = model.withDeadlineAfter(timeoutMilliseconds, TimeUnit.MILLISECONDS);\n      } else {\n        stub = model;\n      }\n      nonCacheResult = stub.batchScore(batch)\n        .getResponsesList().stream().map(r ->\n          r.getScoresList().get(0).getScoreList()).collect(Collectors.toList());\n    } catch (StatusRuntimeException e) {\n      if (e.getStatus().getCode() == Status.DEADLINE_EXCEEDED.getCode()) {\n        throw new TimeoutException(e.getMessage());\n      } else {\n        throw e;\n      }\n    }\n    //\n    List<List<Double>> allResults = new ArrayList<>();\n    int i = 0;\n    for (Request request : requests) {\n      List<Double> result = cachedRequests.get(request);\n      if (result != null) {\n        //System.out.println(\"Adding result from cache\");\n        allResults.add(result);\n      } else {\n        //System.out.println(\"Adding result from remote\");\n        allResults.add(nonCacheResult.get(i++));\n      }\n    }\n","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/languagemodel/bert/RemoteLanguageModel.java#L136-L172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the remote BERT scorer is running and the configured host/port is correct.","Increase the gRPC deadline for large batches or slow networks.","Reduce batch size to lower per-call latency below the deadline.","Inspect the wrapped/rethrown message for the actual gRPC status (UNAVAILABLE, DEADLINE_EXCEEDED) and address it (network, auth, server health).","Add client-side retry with backoff for transient UNAVAILABLE statuses."],"exampleFix":"// before\nstub = RemoteLanguageModelProtocolServiceGrpc.newBlockingStub(channel);\nList<List<Double>> r = model.batchScore(batch);\n// after: smaller batch + longer deadline\nstub = RemoteLanguageModelProtocolServiceGrpc.newBlockingStub(channel)\n    .withDeadlineAfter(120, TimeUnit.SECONDS);\nList<List<Double>> r = model.batchScore(smallerBatch);","handlingStrategy":"try-catch","validationCode":"if (!isServerReachable(host, port))\n  throw new IllegalStateException(\"BERT scorer not reachable at \" + host + \":\" + port);","typeGuard":null,"tryCatchPattern":"try {\n  results = model.batchScore(batch);\n} catch (TimeoutException e) {\n  // retry with smaller batch / longer deadline\n} catch (StatusRuntimeException e) {\n  // check e.getStatus().getCode(); alert on UNAVAILABLE\n}","preventionTips":["Health-check the gRPC scorer before heavy use","Size batches so they finish within the deadline","Set generous deadlines for cold starts","Retry transient UNAVAILABLE with backoff"],"tags":["grpc","timeout","remote-service"],"backgroundTag":"request-timeout","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}