diff --git a/src/app/pages/client/ClientRoot.tsx b/src/app/pages/client/ClientRoot.tsx index cec99db0e..e9e5741f5 100644 --- a/src/app/pages/client/ClientRoot.tsx +++ b/src/app/pages/client/ClientRoot.tsx @@ -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) { {loadState.status === AsyncStatus.Error && ( - {`Failed to load. ${loadState.error.message}`} + <> + {loadState.error.message === IDB_VERSION_CONFLICT ? ( + <> + + Local data is from a newer app version and cannot be read. Clear local + data to continue (you will need to log in again). + + + + ) : ( + {`Failed to load. ${loadState.error.message}`} + )} + )} {startState.status === AsyncStatus.Error && ( {`Failed to start. ${startState.error.message}`} )} - + {loadState.error?.message !== IDB_VERSION_CONFLICT && ( + + )} diff --git a/src/client/initMatrix.ts b/src/client/initMatrix.ts index 498d4f75d..d4205667f 100644 --- a/src/client/initMatrix.ts +++ b/src/client/initMatrix.ts @@ -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 => { const indexedDBStore = new IndexedDBStore({ indexedDB: global.indexedDB, @@ -32,7 +36,15 @@ export const initClient = async (session: Session): Promise => { 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);