languagetool-org/languagetool · error · BadRequestException

Invalid word, cannot be empty or whitespace only

Error message

Invalid word, cannot be empty or whitespace only

What it means

validateWord rejects empty or whitespace-only words before they are stored in a user dictionary, throwing BadRequestException. A user-vocabulary entry must contain at least one non-whitespace character; the server refuses the request as a client input error.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/DatabaseAccessOpenSource.java:323

    } catch (ExecutionException e) {
      logger.warn("Failure in getOrCreateClientId with client '" + client + "': ", e);
      return null;
    }
  }

  @Override
  List<DictGroupEntry> getDictGroups(Long userId) {
    return Collections.emptyList();
  }

  @Override
  Long getOrCreateDictGroup(Long userId, String groupName) {
    throw new NotImplementedException(NON_PREMIUM_MSG);
  }

  private void validateWord(String word) {
    if (word == null || word.trim().isEmpty()) {
      throw new BadRequestException("Invalid word, cannot be empty or whitespace only");
    }
    if (WHITESPACE_PATTERN.matcher(word).matches()) {
      throw new BadRequestException("Invalid word, you can only add words that don't contain spaces: '" + word + "'");
    }
  }

  /** For unit tests only! */
  @Override
  public void createAndFillTestTables(boolean mysql, List<String> skipStatements) {
    try (SqlSession session = sqlSessionFactory.openSession(true)) {
      System.out.println("Setting up tables and adding test user...");
      String[] statements = { "org.languagetool.server.UserDictMapper.createUserTable",
        "org.languagetool.server.UserDictMapper.createIgnoreWordTable" };
      for (String statement : statements) {
        if (skipStatements.contains(statement)) {
          continue;
        }
        if (mysql) {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Trim and check the word for emptiness on the client before calling addWord.
  2. Filter out empty/whitespace-only tokens before batch-adding words.
  3. Fix the upstream extraction logic producing empty tokens.
  4. Ensure the API parameter is actually provided in the request (not dropped/null).

Example fix

// before
server.addWord(userId, word);
// after
String trimmed = word == null ? "" : word.trim();
if (!trimmed.isEmpty()) {
  server.addWord(userId, trimmed);
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidWord(w) {
  return typeof w === 'string' && w.trim().length > 0;
}
if (!isValidWord(word)) throw new Error('word must be non-empty');

Type guard

boolean isNonEmptyString(Object o) {
  return o instanceof String && !((String) o).trim().isEmpty();
}

Try / catch

try {
  api.addWord(userId, word);
} catch (BadRequestException e) {
  if (e.getMessage().contains("cannot be empty")) {
    log.warn("Skipping empty word for user " + userId);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling addWord (or the /vocabulary REST endpoint) with a word that is null, "", or consists only of whitespace (e.g. " ", "\t").

Common situations: Client sends an empty word param from a form/UI; word extracted by a buggy regex that yields empty string; trimming done after validation; JSON body field missing and defaulted to empty.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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