fix: graceful recovery for IDB schema version conflict
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:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user