languagetool-org/languagetool · error · RuntimeException

Error analyzing sentence: '" + match.getSentence().getText()

Error message

Error analyzing sentence: '" + match.getSentence().getText() + "' with rule " + match.getRule().getFullId()

What it means

This RuntimeException is thrown when getAnalyzedToken could not produce an AnalyzedToken for either the determiner or the word at the configured positions — i.e. tagger/disambiguator output has no reading matching the expected pattern. It wraps sentence/rule identification so the offending XML rule can be located.

Source

Thrown at languagetool-language-modules/fr/src/main/java/org/languagetool/rules/fr/WordWithDeterminerFilter.java:86

      if (posDeterminer < 1 || posDeterminer > patternTokens.length) {
        throw new IllegalArgumentException("WordWithDeterminerFilter: Index out of bounds in "
            + match.getRule().getFullId() + ", posDeterminer: " + posWord);
      }
    } else {
      throw new IllegalArgumentException("WordWithDeterminerFilter: undefined parameters wordFrom or determinerFrom in "
          + match.getRule().getFullId());
    }
    AnalyzedTokenReadings atrDeterminer = patternTokens[posDeterminer - 1];
    AnalyzedTokenReadings atrWord = patternTokens[posWord - 1];
    boolean isDeterminerCapitalized = StringTools.isCapitalizedWord(atrDeterminer.getToken());
    boolean isWordCapitalized = StringTools.isCapitalizedWord(atrWord.getToken());
    boolean isDeterminerAllupper = StringTools.isAllUppercase(atrDeterminer.getToken())
        && !atrDeterminer.getToken().equalsIgnoreCase("L'");
    boolean isWordAllupper = StringTools.isAllUppercase(atrWord.getToken());
    AnalyzedToken atDeterminer = getAnalyzedToken(atrDeterminer, detPattern);
    AnalyzedToken atWord = getAnalyzedToken(atrWord, wordPattern);
    if (atWord == null || atDeterminer == null) {
      throw new RuntimeException(
          "Error analyzing sentence: '" + match.getSentence().getText() + "' with rule " + match.getRule().getFullId());
    }
    boolean isNoun = atWord.getPOSTag().startsWith("N") || atWord.getPOSTag().startsWith("Z");
    boolean isAdjective = atWord.getPOSTag().startsWith("J");
    // boolean isParticiple = atWord.getPOSTag().startsWith("V");

    String prefix = "[ZNJ] ";
    if (isNoun && !isAdjective) {
      prefix = "[NZ] ";
    } else if (!isNoun && isAdjective) {
      prefix = "J ";
    }

    // synthesize all forms
    String[][] determinerForms = new String[4][];
    String[][] wordForms = new String[4][];
    for (int i = 0; i < 4; i++) {
      determinerForms[i] = FrenchSynthesizer.INSTANCE.synthesize(atDeterminer, determiner + genderNumber[i], true);

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Inspect the sentence tokens at the positions given by wordFrom/determinerFrom and confirm the tagger assigns a POS tag there.
  2. Add the missing word/form to the French spelling/POS dictionary or adjust the rule's exception settings so it doesn't match unknown tokens.
  3. Relax or correct the token pattern used by getAnalyzedToken so an existing reading matches.
  4. If you control the code, add a null-safe fallback instead of throwing when analysis is inconclusive.

Example fix

// before
AnalyzedToken atWord = getAnalyzedToken(atrWord, wordPattern);
if (atWord == null) throw new RuntimeException(...);
// after
AnalyzedToken atWord = getAnalyzedToken(atrWord, wordPattern);
if (atWord == null) return true; // skip rule gracefully for unanalyzed tokens
Defensive patterns

Strategy: try-catch

Validate before calling

AnalyzedTokenReadings atr = patternTokens[posWord - 1];
if (atr.getAnalyzedTokens().isEmpty()) return true; // skip unanalyzed token

Type guard

static boolean hasReading(AnalyzedTokenReadings atr) { return atr != null && atr.getReadings().size() > 0; }

Try / catch

try { return filter.acceptRuleMatch(match); } catch (RuntimeException e) { log.warn("Filter analysis failed for rule " + match.getRule().getFullId(), e); return true; }

Prevention

When it happens

Trigger: acceptRuleMatch calls getAnalyzedToken(atrDeterminer, detPattern) or getAnalyzedToken(atrWord, wordPattern) and receives null, typically because the token at the given position has no POS tag matching the filter's expectation (e.g. pos tag regex in the filter finds no reading).

Common situations: Rules firing on unanalyzed/unknown tokens (proper nouns, typos, foreign words); French tagger lacking a dictionary entry; positions pointing at punctuation after a pattern change.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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