languagetool-org/languagetool · error · RuntimeException

Required key ' ' not found in properties

Error message

Required key '${key}' not found in properties

What it means

DatabaseHandler.getProperty requires that a database configuration key be present in the loaded Properties object; if Properties.getProperty returns null it throws a RuntimeException naming the missing key. It backs the dbUrl, dbUser, and dbPassword lookups, so any missing DB connection property aborts startup.

Solutions

  1. Open the properties file and add the exact key named in the message (e.g. dbUrl=jdbc:mysql://...)
  2. Check key spelling against what DatabaseHandler expects
  3. Confirm the -d option points to the intended properties file and that it loaded non-empty content

Example fix

// before (db.properties)
databaseUrl=jdbc:mysql://localhost/wiki
// after
dbUrl=jdbc:mysql://localhost/wiki
dbUser=ltuser
dbPassword=secret
Defensive patterns

Strategy: validation

Validate before calling

Properties p = new Properties();
try (FileInputStream in = new FileInputStream(propFile)) { p.load(in); }
for (String key : new String[]{"dbUrl", "dbUser", "dbPassword"}) {
  if (p.getProperty(key) == null) throw new IllegalStateException("Missing required key: " + key);
}

Type guard

static String requireProp(Properties p, String key) {
  String v = p.getProperty(key);
  if (v == null || v.trim().isEmpty()) throw new IllegalStateException("Missing/empty key: " + key);
  return v;
}

Try / catch

try {
  handler = new DatabaseHandler(props);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("not found in properties")) {
    System.err.println("Fix your properties file: " + e.getMessage()); System.exit(2);
  } else throw e;
}

Prevention

When it happens

Trigger: The -d properties file passed to the checker lacks dbUrl, dbUser, or dbPassword, the key is misspelled, or the file is empty/loaded from the wrong path.

Common situations: Copying an old config template missing new keys; typos like 'databaseUrl' vs 'dbUrl'; loading a default/empty properties file because the -d option pointed elsewhere.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at languagetool-wikipedia/src/main/java/org/languagetool/dev/dumpcheck/DatabaseHandler.java:87

      conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
      insertSt = conn.prepareStatement(insertSql);
    } catch (SQLException | IOException e) {
      throw new RuntimeException(e);
    }
    contextTools = new ContextTools();
    contextTools.setContextSize(MAX_CONTEXT_LENGTH);
    contextTools.setErrorMarker(MARKER_START, MARKER_END);
    contextTools.setEscapeHtml(false);
    smallContextTools = new ContextTools();
    smallContextTools.setContextSize(SMALL_CONTEXT_LENGTH);
    smallContextTools.setErrorMarker(MARKER_START, MARKER_END);
    smallContextTools.setEscapeHtml(false);
  }

  private String getProperty(Properties prop, String key) {
    String value = prop.getProperty(key);
    if (value == null) {
      throw new RuntimeException("Required key '" + key + "' not found in properties");
    }
    return value;
  }

  @Override
  protected void handleResult(Sentence sentence, List<RuleMatch> ruleMatches, Language language) {
    try {
      java.sql.Date nowDate = new java.sql.Date(new Date().getTime());
      for (RuleMatch match : ruleMatches) {
        String smallContext = smallContextTools.getContext(match.getFromPos(), match.getToPos(), sentence.getText());
        insertSt.setString(1, language.getShortCode());
        Rule rule = match.getRule();
        insertSt.setString(2, rule.getId());
        insertSt.setString(3, rule.getCategory().getName());
        if (rule instanceof AbstractPatternRule) {
          AbstractPatternRule patternRule = (AbstractPatternRule) rule;
          insertSt.setString(4, patternRule.getSubId());
        } else {

View on GitHub (pinned to 2e990059ce)