Tencent/matrix · error · IllegalStateException
Closed during initialization
Error message
Closed during initialization
What it means
SQLiteLintOwnDatabase.closeDatabase closes the underlying SQLiteDatabase, but if called while the database is mid-initialization (mIsInitializing == true, set inside getDatabase's synchronized openOrCreateDatabase flow), it throws IllegalStateException('Closed during initialization'). This prevents closing a database object that getDatabase is still constructing and returning.
Solutions
- Only call closeDatabase after a successful getDatabase() has returned at least once.
- Serialize lifecycle: perform init (getDatabase) on a single thread before allowing close paths.
- Avoid closing during Application startup/teardown races; guard close with the same lock used by getDatabase.
- Check for leaked async tasks that close the db while lint is initializing.
Example fix
// before
new Thread(() -> ownDatabase.closeDatabase()).start(); // races first getDatabase()
// after
synchronized (ownDatabase) { // after initial getDatabase() completed
ownDatabase.closeDatabase();
} Defensive patterns
Strategy: validation
Validate before calling
// ensure a prior getDatabase() completed before closing
if (!databaseOpenedOnce) { skipClose(); } Try / catch
try {
ownDatabase.closeDatabase();
} catch (IllegalStateException e) {
// initialization still in progress; retry after init completes
} Prevention
- Serialize lifecycle: complete init on one thread before any close
- Guard close paths with the same synchronization as getDatabase
- Avoid background cleanup tasks racing first-use during cold start
When it happens
Trigger: Calling closeDatabase from another thread (or re-entrantly) while getDatabase is still inside openOrCreateDatabase creating/upgrading the db — a race between a closer and the first opener.
Common situations: Shutdown/cleanup code racing first query on a cold start; a component calling closeDatabase before any getDatabase completed; concurrent use of the database object from multiple threads without going through getDatabase's synchronized block.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Call wait() and check its result
- getIssueStorage db not ready
- getDatabase called recursively
- NOT allow to observe with DESTROYED lifecycle owner
- NOT initialized yet
AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08).
Data as JSON: /api/errors/fd017a6bca49ef20.
Report an issue: GitHub.
Appendix: source
Thrown at matrix/matrix-android/matrix-sqlite-lint/matrix-sqlite-lint-android-sdk/src/full/java/com/tencent/sqlitelint/behaviour/persistence/SQLiteLintOwnDatabase.java:86
private volatile SQLiteDatabase mDatabase;
private boolean mIsInitializing;
public SQLiteDatabase getDatabase() {
if (mDatabase == null || !mDatabase.isOpen()) {
synchronized (this) {
if (mDatabase == null || !mDatabase.isOpen()) {
mDatabase = openOrCreateDatabase();
}
}
}
return mDatabase;
}
public synchronized void closeDatabase() {
if (mIsInitializing) {
throw new IllegalStateException("Closed during initialization");
}
if (mDatabase != null && mDatabase.isOpen()) {
mDatabase.close();
mDatabase = null;
}
}
private void onCreate(SQLiteDatabase db) {
SLog.i(TAG, "onCreate");
db.execSQL(IssueStorage.DB_VERSION_1_CREATE_SQL);
for (int i = 0; i < IssueStorage.DB_VERSION_1_CREATE_INDEX.length; i++) {
db.execSQL(IssueStorage.DB_VERSION_1_CREATE_INDEX[i]);
}
}
private void onUpgrade(SQLiteDatabase db, int oldVersion) {View on GitHub (pinned to 3b8293bd65)