languagetool-org/languagetool · error · IllegalStateException

DatabaseAccess.init() has not been called yet or failed

Error message

DatabaseAccess.init() has not been called yet or failed

What it means

DatabaseAccess.getInstance() is a singleton accessor that throws IllegalStateException when the static `instance` field is null. The field is only populated by the static init() method, so this error means the server-side database layer was never initialized (or init() failed and reset instance to null). It is an internal lifecycle error: some code path tried to use the database before setup completed.

Source

Thrown at languagetool-server/src/main/java/org/languagetool/server/DatabaseAccess.java:79

      try {
        Class<DatabaseAccess> clazz = (Class<DatabaseAccess>) JLanguageTool.getClassBroker().forName(className);
        instance = clazz.getConstructor(HTTPServerConfig.class).newInstance(config);
      } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
        throw new RuntimeException(e);
      }
    }
  }

  static synchronized void reset() {
    if (instance != null) {
      instance.sqlSessionFactory = null;
    }
    instance = null;
  }

  static synchronized DatabaseAccess getInstance() {
    if (instance == null) {
      throw new IllegalStateException("DatabaseAccess.init() has not been called yet or failed");
    }
    return instance;
  }

  /**
   * @since 5.7
   * Test if instance is configured and can be used
   */
  static synchronized boolean isReady() {
    return instance != null;
  }

  /**
   * For tests, to avoid waiting for the invalidation period.
   */
  abstract void invalidateCaches();

  abstract boolean addWord(String word, Long userId, String groupName);

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Ensure the server is started with the required database configuration so DatabaseAccess.init(...) is invoked during startup (or call DatabaseAccess.init(...) explicitly in embedded setups).
  2. Check server startup logs for an exception thrown by DatabaseAccess.init(); fix the underlying DB connection/config problem, since a failed init resets instance to null.
  3. Guard calls with a null/state check or only use DatabaseAccess-dependent endpoints after the server reports it is ready.
  4. If you only need the basic (non-database) server, make sure requests do not use premium/username+apiKey features that touch DatabaseAccess.

Example fix

// before
DatabaseAccess db = DatabaseAccess.getInstance(); // IllegalStateException if init not called
// after
if (!DatabaseAccess.isInitialized()) { // check or ensure init ran at startup
  DatabaseAccess.init(sqlSessionFactoryConfig);
}
DatabaseAccess db = DatabaseAccess.getInstance();
Defensive patterns

Strategy: try-catch

Validate before calling

if (!databaseConfigured()) {
  throw new IllegalStateException("Server started without database config; DatabaseAccess will be unavailable");
}

Type guard

boolean dbAvailable() { try { DatabaseAccess.getInstance(); return true; } catch (IllegalStateException e) { return false; } }

Try / catch

try {
  DatabaseAccess db = DatabaseAccess.getInstance();
  // use db
} catch (IllegalStateException e) {
  // fall back to anonymous/no-auth request or surface 'database not configured'
}

Prevention

When it happens

Trigger: Any call to DatabaseAccess.getInstance() before DatabaseAccess.init(...) has run, or after init() failed and set `instance = null`. In practice: server code reaching authentication/word-list features on a server that was started without database configuration.

Common situations: Running languagetool-server without the database/MyBatis config arguments (or premium setup) while a request still hits an endpoint that requires user data; init() throwing during startup (bad DB connection settings) so the singleton stays null; calling DatabaseAccess APIs from custom embedding code without calling init() first.

Related errors


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