{"record":{"id":"a35e527cd5dc21ef","repo":"languagetool-org/languagetool","slug":"invalid-syntax-for-key-value-expected-key-value-a35e52","errorCode":null,"errorMessage":"Invalid syntax for key/value, expected 'key:value', got: '${arg}'","messagePattern":"Invalid syntax for key/value, expected 'key:value', got: '(.+?)'","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilterEvaluator.java","lineNumber":58,"sourceCode":"    this.filter = filter;\n  }\n\n  @Nullable\n  public RuleMatch runFilter(String filterArgs, RuleMatch ruleMatch, AnalyzedTokenReadings[] patternTokens, int patternTokenPos, List<Integer> tokenPositions) throws IOException {\n    Map<String,String> args = getResolvedArguments(filterArgs, patternTokens, patternTokenPos, tokenPositions);\n    return filter.acceptRuleMatch(ruleMatch, args, patternTokenPos, patternTokens, tokenPositions);\n  }\n\n  /**\n   * Resolves the backref arguments, e.g. replaces {@code \\1} by the value of the first token in the pattern.\n   */\n  public Map<String,String> getResolvedArguments(String filterArgs, AnalyzedTokenReadings[] patternTokens, int patternTokenPos, List<Integer> tokenPositions) {\n    Map<String,String> result = new HashMap<>();\n    String[] arguments = WHITESPACE.split(filterArgs);\n    for (String arg : arguments) {\n      int delimPos = arg.indexOf(':');\n      if (delimPos == -1) {\n        throw new RuntimeException(\"Invalid syntax for key/value, expected 'key:value', got: '\" + arg + \"'\");\n      }\n      String key = arg.substring(0, delimPos);\n      String val = arg.substring(delimPos + 1);\n      if (val.startsWith(\"\\\\\")) {\n        int refNumber = Integer.parseInt(val.replace(\"\\\\\", \"\"));\n        if (refNumber > tokenPositions.size()) {\n          throw new RuntimeException(\"Your reference number \" + refNumber + \" is bigger than the number of tokens: \" + tokenPositions.size());\n        }\n        int correctedRef = getSkipCorrectedReference(tokenPositions, refNumber);\n        if (correctedRef >= patternTokens.length) {\n          throw new RuntimeException(\"Your reference number \" + refNumber +\n                  \" is bigger than number of matching tokens: \" + patternTokens.length);\n        }\n        if (result.containsKey(key)) {\n          throw new RuntimeException(\"Duplicate key '\" + key + \"'\");\n        }\n        result.put(key, patternTokens[correctedRef].getToken());\n      } else {","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilterEvaluator.java#L40-L76","documentation":"RuleFilterEvaluator.getResolvedArguments splits the filter attribute's argument string on whitespace and requires each argument to be of the form key:value. If an argument contains no colon, it throws this RuntimeException. The syntax of filter arguments in the rule XML is invalid.","triggerScenarios":"A filterArgs string passed to getResolvedArguments (directly or via evaluating a rule's <filter> element) contains a whitespace-separated token without a colon, e.g. 'no:12 yes' or 'case_sensitive' instead of 'case_sensitive:true'.","commonSituations":"Hand-editing rule XML and forgetting the value after the key; using '=' or '->' instead of ':' as the separator; extra stray token from a bad line wrap; copy-paste that dropped the ':value' part.","solutions":["Give every whitespace-separated argument a key:value form, e.g. `no:1 case_sensitive:true`.","Replace any other separator (=, space-only key) with a colon.","Count tokens: every token in the filter attribute must contain at least one ':'; remove stray tokens.","If you intentionally need a value with spaces, this API cannot express it — restructure the argument or quote-free reformulate it."],"exampleFix":"// before\nString args = \"no:1 case_sensitive\";\n// after\nString args = \"no:1 case_sensitive:true\";","handlingStrategy":"validation","validationCode":"for (String arg : filterArgs.split(\"\\\\s+\")) {\n  if (!arg.contains(\":\")) {\n    throw new IllegalArgumentException(\"Filter argument must be key:value: \" + arg);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  Map<String,String> resolved = evaluator.getResolvedArguments(filterArgs, tokens, pos, positions);\n} catch (RuntimeException e) {\n  if (e.getMessage().startsWith(\"Invalid syntax for key/value\")) {\n    throw new IllegalArgumentException(\"Bad filter args: \" + filterArgs, e);\n  }\n  throw e;\n}","preventionTips":["Adopt the habit of writing every filter argument as key:value.","Never use '=' between key and value in filter attributes.","Lint rule XML files for filter args containing tokens without ':' before committing.","When refactoring values, check the whole args string, not just the edited key."],"tags":["java","argument-parsing","language-tool","rule-filters"],"backgroundTag":"invalid-argument-format","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}