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.

Solutions

  1. Rename the query parameter from 'dict' to 'dicts' in the request URL.
  2. If you need multiple dictionaries, pass them as a comma-separated list: dicts=name1,name2.
  3. 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

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


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/b000570ccb4e1f06. Report an issue: GitHub.

Appendix: 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)