{"record":{"id":"2e775e0a3a144e04","repo":"languagetool-org/languagetool","slug":"the-number-of-forms-and-postags-has-to-be-the-same","errorCode":null,"errorMessage":"The number of forms and postags has to be the same in disambiguation rule with filter IsEnglishWordFilter.","messagePattern":"The number of forms and postags has to be the same in disambiguation rule with filter IsEnglishWordFilter\\.","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/IsEnglishWordFilter.java","lineNumber":68,"sourceCode":"\n  @Override\n  public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> args, int patternTokenPos,\n                                   AnalyzedTokenReadings[] patternTokens, List<Integer> tokenPositions) throws IOException {\n\n    if (tagger == null) {\n      return null;\n    }\n    String[] formPositions = getRequired(\"formPositions\", args).split(\",\");\n    List<String> forms = new ArrayList<>();\n    for (String formPosition : formPositions) {\n      forms.add(patternTokens[getSkipCorrectedReference(tokenPositions, Integer.parseInt(formPosition))].getToken());\n    }\n    boolean isEnglish = true;\n    String postagsStr = getOptional(\"postags\", args);\n    if (postagsStr != null) {\n      String [] postags = postagsStr.split(\",\");\n      if (postags.length != forms.size()) {\n        throw new RuntimeException(\"The number of forms and postags has to be the same in disambiguation rule with \" +\n            \"filter IsEnglishWordFilter.\");\n      }\n      for (int i = 0; i < postags.length; i++) {\n        isEnglish = isEnglish && wordIsTaggedWith(forms.get(i), postags[i]);\n      }\n    } else {\n      for (int i = 0; i < forms.size(); i++) {\n        isEnglish = isEnglish && wordIsTagged(forms.get(i));\n      }\n    }\n    return (isEnglish ? match : null);\n  }\n\n  private boolean wordIsTaggedWith(String word, String postag) throws IOException {\n    return tagger.tag(Collections.singletonList(word)).get(0).matchesPosTagRegex(postag);\n  }\n\n  private boolean wordIsTagged(String word) throws IOException {","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/IsEnglishWordFilter.java#L50-L86","documentation":"IsEnglishWordFilter.acceptRuleMatch checks disambiguation-rule forms against a comma-separated 'postags' argument. When the number of comma-separated postags differs from the number of captured forms, it throws RuntimeException because forms and postags are matched index-by-index.","triggerScenarios":"Using filter=\"IsEnglishWordFilter\" in a disambiguation rule with a 'postags' attribute whose comma-separated tag count does not equal the number of tokens captured by the marker (forms.size()).","commonSituations":"Hand-writing disambiguation XML rules and forgetting a tag or adding an extra comma; adding a token to the marked phrase without updating postags; copying a rule and changing the token count only.","solutions":["Count the marked forms in the disambiguation rule and make the 'postags' attribute contain exactly that many comma-separated tags.","Remove stray commas/whitespace entries in postags that create empty or extra elements.","Test the rule with LanguageTool's rule-validation (e.g. validateRules) so the mismatch is caught before runtime."],"exampleFix":"<!-- before -->\n<filter class=\"org.languagetool.rules.IsEnglishWordFilter\" args=\"postags:NN,VVD\"/>\n<!-- after (two marked forms -> two postags) -->\n<filter class=\"org.languagetool.rules.IsEnglishWordFilter\" args=\"postags:NN,VVD\"/> <!-- ensure exactly 2 marked tokens -->","handlingStrategy":"validation","validationCode":"int formCount = /* number of marked tokens in the disambiguation rule */;\nint tagCount = postagsStr == null ? 0 : postagsStr.split(\",\").length;\nif (postagsStr != null && tagCount != formCount) {\n  throw new IllegalArgumentException(\"postags count (\" + tagCount + \") must equal marked forms (\" + formCount + \")\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  return filter.acceptRuleMatch(match, args, pos, tokens, tokenPositions);\n} catch (RuntimeException e) {\n  throw new RuleFormatException(\"Invalid IsEnglishWordFilter args: \" + e.getMessage(), e);\n}","preventionTips":["Recount postags every time you add/remove a marked token","Run LT's rule validation tools on rule XML in CI","Avoid trailing commas in the postags attribute"],"tags":["java","languagetool","disambiguation-rules","argument-count-mismatch"],"backgroundTag":"invalid-argument-value","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"}