Bug Report
Capacitor Version
"@capacitor/cli": "5.7.0",
"@capacitor/app": "5.0.7",
"@capacitor/core": "5.7.5",
"@capacitor/filesystem": "5.2.1",
"@capacitor/geolocation": "5.0.8",
"@capacitor/haptics": "5.0.7",
"@capacitor/keyboard": "5.0.8",
"@capacitor/network": "5.0.7",
"@capacitor/status-bar": "5.0.7"
Platform(s)
Web (Safari on iOS)
iOS native app (built with Cordova — the app uses cordova-plugin-ionic-webview / WKWebView, and since there is no Capacitor native bridge, @capacitor/filesystem falls back to its web implementation which uses IndexedDB internally. The same IDBDatabase connection closing issue occurs when the WKWebView network process crashes.)
Current Behavior
When Safari's network process crashes (which can happen due to memory pressure, OS resource management, or other system-level events), the web implementation of @capacitor/filesystem becomes permanently broken. All subsequent readFile(), writeFile(), and other file operations fail with:
InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.
This error repeats for every file operation with no recovery. The only way to restore functionality is a full page reload.
The root cause is in initDb() in web.ts. When the database is first opened, the IDBDatabase handle is cached in this._db. When the network process crashes, Safari invalidates the handle and fires the standard IDBDatabase.onclose event. However, the plugin never listens for onclose, so this._db continues to hold the dead handle. The if (this._db !== undefined) guard in initDb() then returns the broken handle on every subsequent call, preventing a fresh indexedDB.open() from ever being called.
Expected Behavior
After the underlying IDB connection is closed by the browser, the plugin should detect this via the onclose event, discard the cached handle, and transparently re-open the database on the next file operation — without requiring a page reload.
Code Reproduction
The issue is in the plugin's initDb() mplementation. Here is the problematic code from web.ts:
async initDb() {
if (this._db !== undefined) {
return this._db;
}
if (!('indexedDB' in window)) {
throw this.unavailable("This browser doesn't support IndexedDB");
}
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
request.onupgradeneeded = FilesystemWeb.doUpgrade;
request.onsuccess = () => {
this._db = request.result;
resolve(request.result);
};
request.onerror = () => reject(request.error);
request.onblocked = () => {
console.warn('db blocked');
};
});
}
Suggested fix — add an onclose handler
To reproduce the issue:
- Open a Capacitor web app using @capacitor/filesystem in Safari
- Perform file operations to confirm they work
- Trigger a network process crash (happens naturally under memory pressure on iOS
- Attempt any file operation — fails with InvalidStateError
- All subsequent operations also fail until page reload
Other Technical Details
IDBDatabase.onclose is part of the IndexedDB specification and is supported in Safari 14+, Chrome, Firefox, and Edge
This is especially impactful for PWAs and home screen web apps on iOS, where long-running sessions make network process crashes more likely
The fix is a single line addition with no breaking changes
Additional Context
Related WebKit change that enables full recovery (new indexedDB.open() calls succeed after crash): WebKit/WebKit#60094
The same onclose handling gap likely affects all other methods that go through dbRequest() and dbIndexRequest(), since they all call initDb() which returns the stale handle.
Bug Report
Capacitor Version
Platform(s)
Web (Safari on iOS)
iOS native app (built with Cordova — the app uses cordova-plugin-ionic-webview / WKWebView, and since there is no Capacitor native bridge, @capacitor/filesystem falls back to its web implementation which uses IndexedDB internally. The same IDBDatabase connection closing issue occurs when the WKWebView network process crashes.)
Current Behavior
When Safari's network process crashes (which can happen due to memory pressure, OS resource management, or other system-level events), the web implementation of @capacitor/filesystem becomes permanently broken. All subsequent readFile(), writeFile(), and other file operations fail with:
InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.This error repeats for every file operation with no recovery. The only way to restore functionality is a full page reload.
The root cause is in initDb() in web.ts. When the database is first opened, the IDBDatabase handle is cached in this._db. When the network process crashes, Safari invalidates the handle and fires the standard IDBDatabase.onclose event. However, the plugin never listens for onclose, so this._db continues to hold the dead handle. The if (this._db !== undefined) guard in initDb() then returns the broken handle on every subsequent call, preventing a fresh indexedDB.open() from ever being called.
Expected Behavior
After the underlying IDB connection is closed by the browser, the plugin should detect this via the onclose event, discard the cached handle, and transparently re-open the database on the next file operation — without requiring a page reload.
Code Reproduction
The issue is in the plugin's initDb() mplementation. Here is the problematic code from web.ts:
Suggested fix — add an onclose handler
To reproduce the issue:
Other Technical Details
IDBDatabase.onclose is part of the IndexedDB specification and is supported in Safari 14+, Chrome, Firefox, and Edge
This is especially impactful for PWAs and home screen web apps on iOS, where long-running sessions make network process crashes more likely
The fix is a single line addition with no breaking changes
Additional Context
Related WebKit change that enables full recovery (new indexedDB.open() calls succeed after crash): WebKit/WebKit#60094
The same onclose handling gap likely affects all other methods that go through dbRequest() and dbIndexRequest(), since they all call initDb() which returns the stale handle.