languagetool-org/languagetool · error · IllegalArgumentException

minOccurrence must be >= 0: ${minOccurrence}

Error message

minOccurrence must be >= 0: ${minOccurrence}

What it means

PatternTokenBuilder.min(int) rejects negative minimum-occurrence values, throwing IllegalArgumentException when val < 0. Note the message mistakenly prints the field minOccurrence (the previous value, possibly null) instead of the parameter val — the offending input is the negative val you passed. Valid minimums are 0 or 1 once passed to the token.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternTokenBuilder.java:85

  public PatternTokenBuilder csTokenRegex(String token) {
    this.token = Objects.requireNonNull(token);
    regexp = true;
    caseSensitive = true;
    return this;
  }

  public PatternTokenBuilder pos(String posTag) {
    return pos(posTag, false);
  }

  public PatternTokenBuilder posRegex(String posTag) {
    return pos(posTag, true);
  }

  /** @since 4.9 */
  public PatternTokenBuilder min(int val) {
    if (val < 0) {
      throw new IllegalArgumentException("minOccurrence must be >= 0: " + minOccurrence);
    }
    minOccurrence = val;
    return this;
  }

  /** @since 4.9 */
  public PatternTokenBuilder max(int val) {
    maxOccurrence = val;
    return this;
  }

  /**
   * Corresponds to {@code <marker>...</marker>} in XML. Note that there
   * can be more tokens with a mark, but then must all be adjacent.
   * @since 4.6
   */
  public PatternTokenBuilder mark(boolean isMarked) {
    this.marker = isMarked;

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Pass a non-negative value; use 0 for an optional token via min(0) combined with an appropriate max.
  2. Clamp before calling: Math.max(0, computedMin).
  3. Fix quantifier arithmetic so the minimum cannot go below 0.
  4. If you intended unlimited, do not use min(); configure max(-1) and set optionality separately.

Example fix

// before
builder.min(count - 2); // can be negative
// after
builder.min(Math.max(0, count - 2));
Defensive patterns

Strategy: validation

Validate before calling

int safeMin = Math.max(0, computedMin);
builder.min(safeMin);

Type guard

boolean isNonNegative(int i) { return i >= 0; }

Try / catch

try {
  builder.min(val);
} catch (IllegalArgumentException e) {
  builder.min(0); // log the negative computed value
}

Prevention

When it happens

Trigger: Calling new PatternTokenBuilder().min(-1) or any negative value; builders computing min counts from arithmetic that can go negative (e.g. max - n).

Common situations: Quantifier arithmetic producing negative minimums; off-by-one in code that decrements counts; passing a sentinel -1 to mean 'unlimited' (which belongs in min()/max() semantics differently here).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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