languagetool-org/languagetool · error · IllegalArgumentException
Use parameter 'dicts', not 'dict' in GET /words API method.
Error message
Use parameter 'dicts', not 'dict' in GET /words API method.
What it means
The GET /v2/words endpoint was changed to accept only the plural parameter 'dicts' (a comma-separated list of dictionary names); the old singular 'dict' parameter is explicitly rejected with an IllegalArgumentException to force callers to migrate. The exception is thrown before any dictionary lookup happens.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/ApiV2.java:196
}
private void handleIpLogMatch(HttpExchange httpExchange, String remoteAddress, Map<String, String> parameters) {
Logger logger = LoggerFactory.getLogger(ApiV2.class);
InetSocketAddress localAddress = httpExchange.getLocalAddress();
logger.info(String.format("Found log-my-IP text in request from: %s to: %s, requestParams: %s", remoteAddress, localAddress.toString(), parameters));
}
private void handleWordsRequest(HttpExchange httpExchange, Map<String, String> params, HTTPServerConfig config) throws Exception {
ensureGetMethod(httpExchange, "/words");
UserLimits limits = getUserLimits(params, config);
DatabaseAccess db = DatabaseAccess.getInstance();
int offset = params.get("offset") != null ? Integer.parseInt(params.get("offset")) : 0;
int limit = params.get("limit") != null ? Integer.parseInt(params.get("limit")) : 10;
logger.info("Started reading dictionary for user: {}, offset: {}, limit: {}, dict_cache: {}, dict: {}",
limits.getPremiumUid(), offset, limit, limits.getDictCacheSize(), params.get("dict"));
if (params.containsKey("dict")) {
throw new IllegalArgumentException("Use parameter 'dicts', not 'dict' in GET /words API method.");
}
// optional parameter: groups in comma separated list
List<String> groups = null;
if (params.containsKey("dicts")) {
groups = Arrays.asList(params.get("dicts").split(","));
} else if (limits.getAccount() != null &&
limits.getAccount().getDefaultDictionary() != null &&
!limits.getAccount().getDefaultDictionary().isEmpty()) {
groups = Collections.singletonList(limits.getAccount().getDefaultDictionary());
}
long start = System.nanoTime();
List<String> words = db.getWords(limits, groups, offset, limit);
//List<String> words = db.getWords(limits.getPremiumUid(), groups, offset, limit);
long durationMilliseconds = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
logger.info("Finished reading dictionary for user: {}, offset: {}, limit: {}, dict_cache: {}, dict: {}, size: {} in {}ms",
limits.getPremiumUid(), offset, limit, limits.getDictCacheSize(), params.get("dict"), words.size(), durationMilliseconds);
writeListResponse("words", words, httpExchange);View on GitHub (pinned to 2e990059ce)
Solutions
- Rename the query parameter from 'dict' to 'dicts' in the request URL.
- If you need multiple dictionaries, pass them as a comma-separated list: dicts=name1,name2.
- Update any client SDK or wrapper that still emits the deprecated 'dict' parameter.
Example fix
// before GET /v2/words?dict=my_personal_dict&username=u&token=t // after GET /v2/words?dicts=my_personal_dict&username=u&token=t
Defensive patterns
Strategy: validation
Validate before calling
const url = new URL('/v2/words', base);
if (url.searchParams.has('dict')) throw new Error('Use "dicts", not "dict", for GET /v2/words'); Prevention
- Use the plural 'dicts' query parameter with a comma-separated list.
- Search client code for 'dict=' and migrate occurrences to 'dicts=' after an upgrade.
- Pin and review server version notes when the /words API changes.
When it happens
Trigger: Calling GET /v2/words with '?dict=my_dict' instead of '?dicts=my_dict'; legacy client code written against the pre-rename API still passing 'dict'.
Common situations: Old integrations or bookmarks written before the API rename; copied example snippets from outdated blog posts or documentation; wrappers that still serialize a 'dict' query parameter.
Understand the failure class
Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.
Related errors
- Missing 'text' or 'data' parameter
- 'lang' parameter missing
- 'ruleId' parameter missing
- Rule '<ruleId>' not found for language <lang> (LanguageTool
- Expected Basic Authentication
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/b000570ccb4e1f06.
Report an issue: GitHub.