{"record":{"id":"42e3fb064867ae8f","repo":"languagetool-org/languagetool","slug":"confusioncheckfilter-index-out-of-bounds-in-m-42e3fb","errorCode":null,"errorMessage":"ConfusionCheckFilter: Index out of bounds in \" + match.getRule().getFullId() + \", VerbFrom: \" + posVerb","messagePattern":"ConfusionCheckFilter: Index out of bounds in \" \\+ match\\.getRule\\(\\)\\.getFullId\\(\\) \\+ \", VerbFrom: \" \\+ posVerb","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/fr/src/main/java/org/languagetool/rules/fr/InterrogativeVerbFilter.java","lineNumber":73,"sourceCode":"                                   AnalyzedTokenReadings[] patternTokens, List<Integer> tokenPositions) throws IOException {\n    /*if (match.getSentence().getText().contains(\"Peut je\")) {\n      int ii=0;\n      ii++;\n    }*/\n    List<String> replacements = new ArrayList<>();\n    String pronounFrom = getRequired(\"PronounFrom\", arguments);\n    String verbFrom = getRequired(\"VerbFrom\", arguments);\n    String desiredPostag = null;\n    List<String> extraSuggestions = new ArrayList<>();\n    if (pronounFrom != null && verbFrom != null) {\n      int posPronoun = Integer.parseInt(pronounFrom);\n      if (posPronoun < 1 || posPronoun > patternTokens.length) {\n        throw new IllegalArgumentException(\"ConfusionCheckFilter: Index out of bounds in \" + match.getRule().getFullId()\n            + \", PronounFrom: \" + posPronoun);\n      }\n      int posVerb = Integer.parseInt(verbFrom);\n      if (posVerb < 1 || posVerb > patternTokens.length) {\n        throw new IllegalArgumentException(\n            \"ConfusionCheckFilter: Index out of bounds in \" + match.getRule().getFullId() + \", VerbFrom: \" + posVerb);\n      }\n\n      //AnalyzedTokenReadings atrVerb = patternTokens[posVerb - 1];\n      AnalyzedTokenReadings atrPronoun = patternTokens[posPronoun - 1];\n      \n      // vous\n      if (atrPronoun.matchesPosTagRegex(\"R pers obj 2 p\")) {\n        desiredPostag = \"V.* (imp) [23] [sp]|V .*(ind|cond).* 2 p\";\n      }\n      // nous\n      else if (atrPronoun.matchesPosTagRegex(\"R pers obj 1 p\")) {\n        desiredPostag = \"V.* (imp) .*|V .*(ind|cond).* 1 p\";\n      }\n      // moi, toi, le, la, lui, nous, vous, les, leur\n      else if (atrPronoun.matchesPosTagRegex(\"R pers obj.*\")) {\n        desiredPostag = \"V.* (imp) .*\";\n      }","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/fr/src/main/java/org/languagetool/rules/fr/InterrogativeVerbFilter.java#L55-L91","documentation":"In the same validation block, InterrogativeVerbFilter parses the 1-based 'VerbFrom' argument and throws this IllegalArgumentException when it is < 1 or exceeds patternTokens.length — the verb position named by the rule does not exist among the matched pattern tokens.","triggerScenarios":"acceptRuleMatch runs on a rule whose \"VerbFrom:N\" argument exceeds the number of tokens in the matched pattern (or is 0/negative), thrown right after the parallel PronounFrom check passes.","commonSituations":"Pattern edits shrinking the token list without renumbering VerbFrom; copy-pasted filter args between rules with different pattern lengths; off-by-one errors due to 1-based positions.","solutions":["Set VerbFrom to a valid 1-based index within the pattern's token count.","Renumber positional arguments after changing the pattern; verify with a rule unit test.","Note the arg name in the message vs the adjacent variable naming; keep PronounFrom and VerbFrom distinct and correctly ordered."],"exampleFix":"<!-- before: pattern has 4 tokens, arg points to 7 -->\n<filter class=\"...InterrogativeVerbFilter\" args=\"PronounFrom:1 VerbFrom:7\"/>\n<!-- after -->\n<filter class=\"...InterrogativeVerbFilter\" args=\"PronounFrom:1 VerbFrom:3\"/>","handlingStrategy":"validation","validationCode":"int verbFrom = Integer.parseInt(args.get(\"VerbFrom\"));\nint patternLen = patternTokens.length;\nif (verbFrom < 1 || verbFrom > patternLen) {\n    throw new IllegalArgumentException(\"VerbFrom must be 1..\" + patternLen);\n}","typeGuard":null,"tryCatchPattern":"try { return filter.acceptRuleMatch(match, args, pos, tokens, tp); } catch (IllegalArgumentException e) { LOG.error(\"Rule \" + match.getRule().getFullId() + \": \" + e.getMessage()); return match; }","preventionTips":["Validate both PronounFrom and VerbFrom together against pattern length.","Renumber args after pattern token changes.","Keep filter args per-rule rather than copy-pasting across rules with different patterns."],"tags":["java","languagetool","index-out-of-bounds","rule-configuration","french"],"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"}