languagetool-org/languagetool · error · IllegalArgumentException
dbLogging can only be true if dbDriver, dbUrl, dbUsername…
Error message
dbLogging can only be true if dbDriver, dbUrl, dbUsername, and dbPassword are all set
What it means
When 'dbLogging=true' the server logs rule matches to a database, which requires complete JDBC connection settings: dbDriver, dbUrl, dbUsername, and dbPassword. If any of these is null, HTTPServerConfig throws this IllegalArgumentException because logging to the DB would fail.
Solutions
- Set all four properties: dbDriver (e.g. com.mysql.cj.jdbc.Driver), dbUrl, dbUsername, dbPassword
- Inject the missing values at deploy time via environment-variable substitution in the properties template
- Set 'dbLogging=false' if database logging is not actually needed
Example fix
// before (server.properties) dbLogging=true dbUrl=jdbc:mysql://localhost/ltlogs // after (server.properties) dbLogging=true dbDriver=com.mysql.cj.jdbc.Driver dbUrl=jdbc:mysql://localhost/ltlogs dbUsername=ltuser dbPassword=secret
Defensive patterns
Strategy: validation
Validate before calling
if (Boolean.parseBoolean(props.getProperty("dbLogging", "false"))) {
for (String k : new String[]{"dbDriver", "dbUrl", "dbUsername", "dbPassword"}) {
if (props.getProperty(k) == null) throw new IllegalStateException("dbLogging=true requires " + k);
}
} Try / catch
try {
serverConfig = new HTTPServerConfig(props);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("dbLogging can only be true")) {
log.error("Incomplete DB config; check dbDriver/dbUrl/dbUsername/dbPassword");
}
throw e;
} Prevention
- Inject DB credentials via environment-variable placeholders in the properties template
- Keep db settings together in one config block so none are dropped
- Set dbLogging=false by default and enable it only with a complete DB section
When it happens
Trigger: Server properties file contains 'dbLogging=true' but is missing one or more of dbDriver, dbUrl, dbUsername, or dbPassword.
Common situations: Credentials omitted from the config for security but not injected via environment/template; partial config copied from another environment; dbDriver/dbUrl forgotten while only user/password set.
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
- beolingusFile not found:
- Cannot use premiumOnly=true with non-premium version
- Could not load properties from ''
- Invalid value for cacheSize: , use 0 to deactivate cache
- ngramLangIdentData does not exist or is a directory (needs…
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/23190562b293de00.
Report an issue: GitHub.
Appendix: source
Thrown at languagetool-server/src/main/java/org/languagetool/server/HTTPServerConfig.java:462
gracefulDatabaseFailure = Boolean.parseBoolean(getOptionalProperty(props, "gracefulDatabaseFailure", "false").trim());
dbDriver = getOptionalProperty(props, "dbDriver", null);
dbUrl = getOptionalProperty(props, "dbUrl", null);
dbUsername = getOptionalProperty(props, "dbUsername", null);
dbPassword = getOptionalProperty(props, "dbPassword", null);
dbTimeoutSeconds = Integer.parseInt(getOptionalProperty(props, "dbTimeoutSeconds", "10"));
dbMaxConnections = Integer.parseInt(getOptionalProperty(props, "dbMaxConnections", "10"));
databaseErrorRateThreshold = Integer.parseInt(getOptionalProperty(props, "dbErrorRateThreshold", "50"));
databaseTimeoutRateThreshold = Integer.parseInt(getOptionalProperty(props, "dbTimeoutRateThreshold", "100"));
databaseDownIntervalSeconds = Integer.parseInt(getOptionalProperty(props, "dbDownIntervalSeconds", "10"));
dbLogging = Boolean.valueOf(getOptionalProperty(props, "dbLogging", "false").trim());
passwortLoginAccessListPath = getOptionalProperty(props, "passwortLoginAccessListPath", "");
prometheusMonitoring = Boolean.valueOf(getOptionalProperty(props, "prometheusMonitoring", "false").trim());
prometheusPort = Integer.parseInt(getOptionalProperty(props, "prometheusPort", "9301"));
skipLoggingRuleMatches = Boolean.valueOf(getOptionalProperty(props, "skipLoggingRuleMatches", "false").trim());
skipLoggingChecks = Boolean.valueOf(getOptionalProperty(props, "skipLoggingChecks", "false").trim());
if (dbLogging && (dbDriver == null || dbUrl == null || dbUsername == null || dbPassword == null)) {
throw new IllegalArgumentException("dbLogging can only be true if dbDriver, dbUrl, dbUsername, and dbPassword are all set");
}
slowRuleLoggingThreshold = Integer.valueOf(getOptionalProperty(props, "slowRuleLoggingThreshold", "-1"));
disabledRuleIds = Arrays.asList(getOptionalProperty(props, "disabledRuleIds", "").split(",\\s*"));
localApiMode = Boolean.parseBoolean(getOptionalProperty(props, "localApiMode", "false"));
motherTongue = getOptionalProperty(props, "motherTongue", "en-US");
String preferredLanguages = getOptionalProperty(props, "preferredLanguages", "").replace(" ", "");
if (!preferredLanguages.equals("")) {
this.preferredLanguages = Arrays.asList(preferredLanguages.split(","));
}
dictLimitUser = Integer.valueOf(getOptionalProperty(props, "dictLimitUser", "0"));
dictLimitTeam = Integer.valueOf(getOptionalProperty(props, "dictLimitTeam", "0"));
styleGuideLimitUser = Integer.valueOf(getOptionalProperty(props, "styleGuideLimitUser", "0"));
styleGuideLimitTeam = Integer.valueOf(getOptionalProperty(props, "styleGuideLimitTeam", "0"));
requestLimitAccessToken = getOptionalProperty(props, "requestLimitAccessToken", null);
jwtSecret = getOptionalProperty(props, "jwtSecret", null);
externalRolloutServiceUrl = getOptionalProperty(props, "externalRolloutServiceUrl", null);
externalRolloutServiceApiKey = getOptionalProperty(props, "externalRolloutServiceApiKey", null);
View on GitHub (pinned to 2e990059ce)