fix: graceful recovery for IDB schema version conflict
CI / Build & Quality Checks (push) Has been cancelled

When matrix-sdk is briefly upgraded then reverted, the local IndexedDB
schema version is higher than the SDK expects. Detect the VersionError
DOMException and show a clear 'Clear local data and reload' button
instead of a cryptic error message.
This commit is contained in:
Lotus Bot
2026-05-21 23:50:24 -04:00
parent 6b54926552
commit 41bf176919
2 changed files with 38 additions and 7 deletions
+25 -6
View File
@@ -19,6 +19,7 @@ import React, { MouseEventHandler, ReactNode, useCallback, useEffect, useState }
import {
clearCacheAndReload,
clearLoginData,
IDB_VERSION_CONFLICT,
initClient,
logoutClient,
startClient,
@@ -201,16 +202,34 @@ export function ClientRoot({ children }: ClientRootProps) {
<Dialog>
<Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
{loadState.status === AsyncStatus.Error && (
<Text>{`Failed to load. ${loadState.error.message}`}</Text>
<>
{loadState.error.message === IDB_VERSION_CONFLICT ? (
<>
<Text>
Local data is from a newer app version and cannot be read. Clear local
data to continue (you will need to log in again).
</Text>
<Button variant="Critical" onClick={clearLoginData}>
<Text as="span" size="B400">
Clear local data and reload
</Text>
</Button>
</>
) : (
<Text>{`Failed to load. ${loadState.error.message}`}</Text>
)}
</>
)}
{startState.status === AsyncStatus.Error && (
<Text>{`Failed to start. ${startState.error.message}`}</Text>
)}
<Button variant="Critical" onClick={mx ? () => startMatrix(mx) : loadMatrix}>
<Text as="span" size="B400">
Retry
</Text>
</Button>
{loadState.error?.message !== IDB_VERSION_CONFLICT && (
<Button variant="Critical" onClick={mx ? () => startMatrix(mx) : loadMatrix}>
<Text as="span" size="B400">
Retry
</Text>
</Button>
)}
</Box>
</Dialog>
</Box>
+13 -1
View File
@@ -11,6 +11,10 @@ type Session = {
deviceId: string;
};
// Thrown when the local IndexedDB has a higher schema version than this SDK expects.
// This happens after a downgrade (e.g. matrix-js-sdk was briefly upgraded and then reverted).
export const IDB_VERSION_CONFLICT = 'IDB_VERSION_CONFLICT';
export const initClient = async (session: Session): Promise<MatrixClient> => {
const indexedDBStore = new IndexedDBStore({
indexedDB: global.indexedDB,
@@ -32,7 +36,15 @@ export const initClient = async (session: Session): Promise<MatrixClient> => {
verificationMethods: ['m.sas.v1'],
});
await indexedDBStore.startup();
try {
await indexedDBStore.startup();
} catch (e) {
// IDB VersionError = local DB was written by a newer SDK version (schema downgrade).
if (e instanceof DOMException && e.name === 'VersionError') {
throw new Error(IDB_VERSION_CONFLICT);
}
throw e;
}
await mx.initRustCrypto();
mx.setMaxListeners(50);