languagetool-org/languagetool · error · RuntimeException
Invalid syntax for key/value, expected 'key:value', got: '${
Error message
Invalid syntax for key/value, expected 'key:value', got: '${arg}' What it means
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.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilterEvaluator.java:58
this.filter = filter;
}
@Nullable
public RuleMatch runFilter(String filterArgs, RuleMatch ruleMatch, AnalyzedTokenReadings[] patternTokens, int patternTokenPos, List<Integer> tokenPositions) throws IOException {
Map<String,String> args = getResolvedArguments(filterArgs, patternTokens, patternTokenPos, tokenPositions);
return filter.acceptRuleMatch(ruleMatch, args, patternTokenPos, patternTokens, tokenPositions);
}
/**
* Resolves the backref arguments, e.g. replaces {@code \1} by the value of the first token in the pattern.
*/
public Map<String,String> getResolvedArguments(String filterArgs, AnalyzedTokenReadings[] patternTokens, int patternTokenPos, List<Integer> tokenPositions) {
Map<String,String> result = new HashMap<>();
String[] arguments = WHITESPACE.split(filterArgs);
for (String arg : arguments) {
int delimPos = arg.indexOf(':');
if (delimPos == -1) {
throw new RuntimeException("Invalid syntax for key/value, expected 'key:value', got: '" + arg + "'");
}
String key = arg.substring(0, delimPos);
String val = arg.substring(delimPos + 1);
if (val.startsWith("\\")) {
int refNumber = Integer.parseInt(val.replace("\\", ""));
if (refNumber > tokenPositions.size()) {
throw new RuntimeException("Your reference number " + refNumber + " is bigger than the number of tokens: " + tokenPositions.size());
}
int correctedRef = getSkipCorrectedReference(tokenPositions, refNumber);
if (correctedRef >= patternTokens.length) {
throw new RuntimeException("Your reference number " + refNumber +
" is bigger than number of matching tokens: " + patternTokens.length);
}
if (result.containsKey(key)) {
throw new RuntimeException("Duplicate key '" + key + "'");
}
result.put(key, patternTokens[correctedRef].getToken());
} else {View on GitHub (pinned to 2e990059ce)
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.
Example fix
// before String args = "no:1 case_sensitive"; // after String args = "no:1 case_sensitive:true";
Defensive patterns
Strategy: validation
Validate before calling
for (String arg : filterArgs.split("\\s+")) {
if (!arg.contains(":")) {
throw new IllegalArgumentException("Filter argument must be key:value: " + arg);
}
} Try / catch
try {
Map<String,String> resolved = evaluator.getResolvedArguments(filterArgs, tokens, pos, positions);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Invalid syntax for key/value")) {
throw new IllegalArgumentException("Bad filter args: " + filterArgs, e);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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'.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Filter class '${className}' must implement interface ${RuleF
- Your reference number ${refNumber} is bigger than the number
- Could not create filter class using constructor ${constructo
- Could not find filter class: '${className}' - make sure to u
- WrongParameterNumberException
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/a35e527cd5dc21ef.
Report an issue: GitHub.