languagetool-org/languagetool · error

No hits for

Error message

No hits for 

What it means

StartTokenCounter counts occurrences of sentence-start tokens in an ngram Lucene index. For every term looked up via searcher.search(new TermQuery(new Term("ngram", term)), 3), it requires at least one hit; a totalHits of 0 means the term is absent from the index, so counting cannot proceed and it throws.

Solutions

  1. Confirm the Lucene index was built completely and from the same corpus the terms come from; rebuild with AggregatedNgramToLucene if needed.
  2. Log and skip unknown terms instead of failing: change the throw to a warning + continue for rare OOV tokens.
  3. Check that the query field name "ngram" and term formatting (including any _POS suffix) exactly match what getDoc() indexed.
  4. Open the index with Luke or a small probe program to verify the missing term really is absent.

Example fix

// before
TopDocs topDocs = searcher.search(new TermQuery(new Term("ngram", term)), 3);
if (topDocs.totalHits == 0) {
  throw new RuntimeException("No hits for " + term + ": " + topDocs.totalHits);
}
// after
TopDocs topDocs = searcher.search(new TermQuery(new Term("ngram", term)), 3);
if (topDocs.totalHits == 0) {
  System.err.println("WARN: no index hits, skipping term: " + term);
  continue;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// probe the index before batch counting
try (IndexReader reader = DirectoryReader.open(indexDir)) {
  IndexSearcher s = new IndexSearcher(reader);
  if (s.search(new TermQuery(new Term("ngram", term)), 1).totalHits == 0) {
    System.err.println("Term not in index: " + term);
  }
}

Try / catch

try {
  TopDocs topDocs = searcher.search(new TermQuery(new Term("ngram", term)), 3);
  if (topDocs.totalHits == 0) { /* log OOV and continue */ }
} catch (RuntimeException e) {
  skippedTerms.add(term);
}

Prevention

When it happens

Trigger: Querying the Lucene ngram index with a term that was never indexed — e.g. the input corpus (parsed TSV, POS-stripped) contains a token whose exact surface form with the trailing _POS suffix does not exist in the index, the index was built from a different/smaller corpus, or the field name "ngram" doesn't match the indexed field.

Common situations: Building the Lucene index from one ngram corpus (e.g. Google Books) but querying with terms from another (web); index build interrupted so documents are missing; casing or morphological suffix mismatch between query term and indexed ngram strings.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at languagetool-dev/src/main/java/org/languagetool/dev/archive/StartTokenCounter.java:64

    File dir = new File("/data/google-ngram-index/en/2grams");
    try (FSDirectory directory = FSDirectory.open(dir.toPath());
         IndexReader reader = DirectoryReader.open(directory)) {
      IndexSearcher searcher = new IndexSearcher(reader);
      Fields fields = MultiFields.getFields(reader);
      Terms ngrams = fields.terms("ngram");
      TermsEnum iterator = ngrams.iterator();
      BytesRef next;
      int i = 0;
      while ((next = iterator.next()) != null) {
        String term = next.utf8ToString();
        if (term.startsWith(LanguageModel.GOOGLE_SENTENCE_START)) {
          if (term.matches(".*_(ADJ|ADV|NUM|VERB|ADP|NOUN|PRON|CONJ|DET|PRT)$")) {
            //System.out.println("ignore: " + term);
            continue;
          }
          TopDocs topDocs = searcher.search(new TermQuery(new Term("ngram", term)), 3);
          if (topDocs.totalHits == 0) {
            throw new RuntimeException("No hits for " + term + ": " + topDocs.totalHits);
          } else if (topDocs.totalHits == 1) {
            int docId = topDocs.scoreDocs[0].doc;
            Document document = reader.document(docId);
            Long count = Long.parseLong(document.get("count"));
            //System.out.println(term + " -> " + count);
            totalCount += count;
            if (++i % 10_000 == 0) {
              System.out.println(i + " ... " + totalCount);
            }
          } else {
            throw new RuntimeException("More hits than expected for " + term + ": " + topDocs.totalHits);
          }
        }
      }
    }
    System.out.println("==> " + totalCount);
  }
  

View on GitHub (pinned to 2e990059ce)