languagetool-org/languagetool · error · IllegalArgumentException

factor must be > 0: " + score

Error message

factor must be > 0: " + score

What it means

ScoredConfusionSet's constructor documents that the score/factor threshold must be strictly greater than 0; a score <= 0 would make every alternative 'considered correct' vacuously or nonsensically, so it throws IllegalArgumentException with this message.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/ScoredConfusionSet.java:43

/**
 * Words that can easily be confused - for internal use only.
 * Even though there can be more words in the confusionWords, usually there
 * are two, as the factor is specific for this pair of words.
 * A ScoredConfusionSet has a positive score associated with it.
 * TODO remove code duplication with ConfusionSet
 */
public class ScoredConfusionSet {

  private List<ConfusionString> confusionWords;
  private final float score;

  /**
   * @param score the score that a string must get at least to be considered a correction, must be &gt; 0
   */
  public ScoredConfusionSet(float score, List<ConfusionString> words) {
    if (score <= 0) {
      throw new IllegalArgumentException("factor must be > 0: " + score);
    }
    this.score = score;
    confusionWords = words;
  }

  /* Alternative must be at least this much more probable to be considered correct. */
  public float getScore() {
    return score;
  }

  public List<String> getConfusionTokens() {
    return confusionWords.stream().map(ConfusionString::getString).collect(Collectors.toList());
  }

  public List<Optional<String>> getTokenDescriptions() {
    return confusionWords.stream()
            .map(ConfusionString::getDescription)
            .map(Optional::ofNullable)

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Pass a positive score (e.g. 0.5f) when constructing ScoredConfusionSet.
  2. Check the source data/config that supplies the score; fix zero or negative entries.
  3. Add a caller-side guard or default (e.g. Math.max(score, MIN_SCORE)) before constructing.

Example fix

// before
float score = Float.parseFloat(props.getProperty("factor", "0"));
ScoredConfusionSet set = new ScoredConfusionSet(score, words);
// after
float score = Float.parseFloat(props.getProperty("factor", "1.0"));
if (score <= 0) throw new IllegalArgumentException("confusion set factor must be > 0");
ScoredConfusionSet set = new ScoredConfusionSet(score, words);
Defensive patterns

Strategy: validation

Validate before calling

if (!(score > 0) || Float.isNaN(score)) {
  throw new IllegalArgumentException("ScoredConfusionSet score must be > 0, got: " + score);
}

Type guard

boolean isValidScore(float score) { return score > 0.0f && !Float.isNaN(score); }

Try / catch

try {
  set = new ScoredConfusionSet(score, words);
} catch (IllegalArgumentException e) {
  LOG.warn("Falling back to default score: {}", e.getMessage());
  set = new ScoredConfusionSet(1.0f, words);
}

Prevention

When it happens

Trigger: Instantiating new ScoredConfusionSet(score, words) with score = 0, negative, or NaN-derived value <= 0, e.g. from a mis-parsed config value or default initialization.

Common situations: Confusion-set rules loaded from data files where the score column was missing/zero, float parsing of empty strings yielding 0, or copy-pasted example code with a placeholder score.

Related errors


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