languagetool-org/languagetool · error · RuntimeException

<regexp> rules currently cannot be used together with <antip

Error message

<regexp> rules currently cannot be used together with <antipattern>. Rule id: 

What it means

Regex-based rules (<regexp>) do not support anti-patterns, unlike token-pattern rules. If any rule- or rulegroup-level <antipattern> elements are present when building a RegexPatternRule, createRules throws this RuntimeException.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java:794

        rule.addToneTags(ruleToneTags);
        rule.addToneTags(ruleGroupToneTags);
        rule.setSourceFile(sourceFile);
        rule.setMinPrevMatches(minPrevMatches);
        rule.setDistanceTokens(distanceTokens);
        rule.setXmlLineNumber(xmlLineNumber);
      } else if (regex.length() > 0) {
        // UNICODE_CHARACTER_CLASS (equivalent to the inline (?U) flag) makes \b, \w, \d and \s
        // Unicode-aware. Without it the behavior of word boundaries next to non-ASCII letters
        // depends on the JDK version (it changed between JDK 17 and JDK 21), which breaks many
        // <regexp> rules. Setting it here avoids adding (?U) by hand to every <regexp> pattern.
        int flags = Pattern.UNICODE_CHARACTER_CLASS | (regexCaseSensitive ? 0 : Pattern.CASE_INSENSITIVE|Pattern.UNICODE_CASE);
        String regexStr = regex.toString();
        if (regexMode == RegexpMode.SMART) {
          // Note: it's not that easy to add \b because the regex might look like '(foo)' or '\d' so we cannot just look at the last character
          regexStr = replaceSpacesInRegex(regexStr);
        }
        if (ruleAntiPatterns.size() > 0 || rulegroupAntiPatterns.size() > 0) {
          throw new RuntimeException("<regexp> rules currently cannot be used together with <antipattern>. Rule id: " + id + "[" + subId + "]");
        }
        rule = new RegexPatternRule(id, name, message.toString(), shortMessage, suggestionsOutMsg.toString(), language, Pattern.compile(regexStr, flags), regexpMark);
        rule.setSourceFile(sourceFile);
      } else {
        throw new IllegalStateException("Neither '<pattern>' tokens nor '<regexp>' is set in rule '" + id + "'");
      }
      setRuleFilter(filterClassName, filterArgs, rule);
      prepareRule(rule);
      rules.add(rule);
    } else {
      PatternToken patternToken = elemList.get(numElement);
      if (patternToken.hasOrGroup()) {
        // When creating a new rule, we finally clear the backed-up variables. All the elements in
        // the OR group should share the values of backed-up variables. That's why these variables
        // are backed-up.
        List<Match> suggestionMatchesBackup = new ArrayList<>(suggestionMatches);
        List<Match> suggestionMatchesOutMsgBackup =  new ArrayList<>(suggestionMatchesOutMsg);
        int startPosBackup = startPos;

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Remove the <antipattern> element(s) from the regexp rule / rulegroup
  2. Rewrite the exclusion logic directly into the regular expression (e.g. negative lookahead)
  3. Convert the rule back to token-based <pattern> form if antipatterns are essential

Example fix

// before
<rule id="X"><antipattern><token>ok</token></antipattern><regexp>...</regexp></rule>
// after
<rule id="X"><regexp>(?!ok\b)...</regexp></rule>
Defensive patterns

Strategy: validation

Validate before calling

// Reject combination of regexp and antipattern
NodeList rx = doc.getElementsByTagName("regexp");
if (rx.getLength() > 0 && (doc.getElementsByTagName("antipattern").getLength() > 0))
  throw new IllegalStateException("<regexp> with <antipattern> is unsupported");

Try / catch

try { loader.parse(ruleXml, lang); } catch (RuntimeException e) { if (e.getMessage().contains("cannot be used together with <antipattern>")) { log.error("Drop antipatterns or convert to pattern rule"); } throw e; }

Prevention

When it happens

Trigger: A rule whose body uses <regexp> instead of <pattern> while the rule or its enclosing <rulegroup> contains one or more <antipattern> elements.

Common situations: Converting a token-based rule to a regex rule without removing its antipatterns; adding antipatterns to a group that also contains a regexp rule.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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