languagetool-org/languagetool · error · RuntimeException

Exception during search for query + query + on rule + rule.g

Error message

Exception during search for query + query + on rule + rule.getId()

What it means

findRuleMatchesOnIndex collects any Exception thrown by the worker search thread and rethrows it as a RuntimeException wrapping the original, annotated with the query and rule ID. It signals the search thread itself failed with an unexpected exception (anything other than SearchTimeoutException).

Source

Thrown at languagetool-wikipedia/src/main/java/org/languagetool/dev/index/Searcher.java:190

          searchThread.join(maxSearchTimeMillis);
        } else {
          searchThread.join(Integer.MAX_VALUE);
        }
      } catch (InterruptedException e) {
        throw new RuntimeException("Search thread got interrupted for query " + query, e);
      }
      if (searchThread.isAlive()) {
        // join() timed out and the thread is still running, so its result isn't ready yet -
        // interrupt it and bail out instead of falling through with a null result
        searchThread.interrupt();
        throw new SearchTimeoutException("Search timeout of " + maxSearchTimeMillis + "ms reached for query " + query);
      }
      Exception exception = runnable.getException();
      if (exception != null) {
        if (exception instanceof SearchTimeoutException) {
          throw (SearchTimeoutException)exception;
        }
        throw new RuntimeException("Exception during search for query " + query + " on rule " + rule.getId(), exception);
      }

      List<MatchingSentence> matchingSentences = runnable.getMatchingSentences();
      SearcherResult searcherResult = new SearcherResult(matchingSentences, runnable.docsChecked, query);
      searcherResult.setMaxDocChecked(runnable.getMaxDocChecked());
      searcherResult.setHasTooManyLuceneMatches(runnable.hasTooManyLuceneMatches());
      searcherResult.setLuceneMatchCount(runnable.getLuceneMatchCount());
      searcherResult.setSkipHits(skipHits);
      searcherResult.setNumDocs(runnable.numDocs);
      if (runnable.hasTooManyLuceneMatches()) {
        // more potential matches than we can check in an acceptable time :-(
        searcherResult.setDocCount(maxHits);
      } else {
        searcherResult.setDocCount(getDocCount(indexSearcher));
      }
      //TODO: the search itself could also timeout, don't just ignore that:
      //searcherResult.setResultIsTimeLimited(limitedTopDocs.resultIsTimeLimited);
      return searcherResult;

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Inspect the cause exception printed in the stack trace to find the real failure
  2. Fix the malformed query or rule that caused the underlying exception
  3. Verify the Lucene index is not corrupted (rebuild it if IO errors persist)
  4. If intended, catch RuntimeException and check the cause for SearchTimeoutException handling

Example fix

// before
throw new RuntimeException("Exception during search for query " + query + " on rule " + rule.getId(), exception);
// after (caller-side handling)
try {
  result = searcher.findRuleMatchesOnIndex(query, rule, timeout);
} catch (RuntimeException e) {
  LOG.error("search failed for rule " + rule.getId(), e.getCause());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate query syntax before submitting
Query q = parser.parse(queryString); // throws ParseException early

Try / catch

try {
  result = searcher.findRuleMatchesOnIndex(query, rule, timeout);
} catch (RuntimeException e) {
  Throwable cause = e.getCause();
  LOG.error("search failed on rule " + rule.getId() + ": " + cause, cause);
}

Prevention

When it happens

Trigger: The worker search thread (runnable) threw a non-timeout Exception during query execution for the given rule; the wrapper rethrows it here.

Common situations: Lucene parse errors from a malformed query, IO errors reading the index, bugs in rule handling inside the search thread; the original stack trace is the cause of this RuntimeException.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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