{"record":{"id":"3087c178b6e739d4","repo":"languagetool-org/languagetool","slug":"maxoccurrences-should-be-between-1-and-byte-max","errorCode":null,"errorMessage":"maxOccurrences should be between -1 and ${Byte.MAX_VALUE} but was: ${i}","messagePattern":"maxOccurrences should be between -1 and (.+?) but was: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternToken.java","lineNumber":429,"sourceCode":"   * @param i currently only {@code 0} and {@code 1} are supported\n   */\n  public void setMinOccurrence(int i) {\n    if (i != 0 && i != 1) {\n      throw new IllegalArgumentException(\"minOccurrences must be 0 or 1: \" + i);\n    }\n    setFlag(MAY_BE_OMITTED_MASK, i == 0);\n  }\n\n  /**\n   * The maximum number of times this element may occur.\n   * @param i a number &gt;= 1 or {@code -1} for unlimited occurrences\n   */\n  public void setMaxOccurrence(int i) {\n    if (i == 0) {\n      throw new IllegalArgumentException(\"maxOccurrences may not be 0\");\n    }\n    if (i < -1 || i > Byte.MAX_VALUE) {\n      throw new IllegalArgumentException(\"maxOccurrences should be between -1 and \" + Byte.MAX_VALUE + \" but was: \" + i);\n    }\n    maxOccurrence = (byte) i;\n  }\n\n  /**\n   * Checks if the element has an exception for a previous token.\n   * @return True if the element has a previous token matching exception.\n   */\n  public boolean hasPreviousException() {\n    return rareFields != null && rareFields.previousExceptions.length > 0;\n  }\n\n  /**\n   * Checks if the element has an exception for a next scope.\n   * (only used for testing)\n   * @return True if the element has exception for the next scope.\n   */\n  public boolean hasNextException() {","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternToken.java#L411-L447","documentation":"PatternToken.setMaxOccurrence(int) also enforces the storage range: values must be -1 (unlimited) or between 1 and Byte.MAX_VALUE (127), since maxOccurrence is stored as a byte. Values < -1 or > 127 throw IllegalArgumentException with the offending value in the message.","triggerScenarios":"Calling setMaxOccurrence(-2) or setMaxOccurrence(128+), directly or from parsed rule XML maxOccurs attributes during build() (see testTwoMaxOccurrencesWithAnyToken).","commonSituations":"Rule authors writing maxOccurs=\"500\" to mean 'many' or 'unlimited' instead of -1; computed maximums from token counts exceeding 127; copy-pasted regex quantifiers like {2,300} translated naively.","solutions":["Use -1 for unlimited instead of a number larger than 127.","Clamp computed values to Byte.MAX_VALUE before calling setMaxOccurrence.","Fix rule XML maxOccurs attributes to be within 1..127 or exactly -1.","Range-validate at rule-configuration load time and fail fast with your own clearer message."],"exampleFix":"// before\npToken.setMaxOccurrence(500);\n// after\npToken.setMaxOccurrence(-1); // unlimited, or clamp: Math.min(500, Byte.MAX_VALUE)","handlingStrategy":"validation","validationCode":"int safeMax = (maxOccurrence < -1) ? -1 : Math.min(maxOccurrence, Byte.MAX_VALUE);\npToken.setMaxOccurrence(safeMax);","typeGuard":"boolean isValidMaxRange(int i) { return i >= -1 && i <= Byte.MAX_VALUE && i != 0; }","tryCatchPattern":"try {\n  token.setMaxOccurrence(max);\n} catch (IllegalArgumentException e) {\n  token.setMaxOccurrence(-1); // fall back to unlimited\n}","preventionTips":["Use -1 for unlimited occurrences instead of large numbers.","Clamp to 1..127 range before calling.","Audit maxOccurs attributes in rule XML for values outside -1..127.","Validate quantifier configs when rules are loaded, not at match time."],"tags":["validation","range-check","java"],"backgroundTag":"value-out-of-range","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}