diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index 0575d2163f844a8673fb2b0efb8aae3c9e6a47ee..47e44c43dc114e05553386002fb918b34f66265c 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -592,10 +592,11 @@ export async function restoreSessionFromStorage(opts?: { ignoreGuest?: boolean }
         if (pickleKey) {
             logger.log(`Got pickle key for ${userId}|${deviceId}`);
         } else {
-            logger.log("No pickle key available");
+            logger.log(`No pickle key available for ${userId}|${deviceId}`);
         }
         const decryptedAccessToken = await tryDecryptToken(pickleKey, accessToken, ACCESS_TOKEN_IV);
-        const decryptedRefreshToken = await tryDecryptToken(pickleKey, refreshToken, REFRESH_TOKEN_IV);
+        const decryptedRefreshToken =
+            refreshToken && (await tryDecryptToken(pickleKey, refreshToken, REFRESH_TOKEN_IV));
 
         const freshLogin = sessionStorage.getItem("mx_fresh_login") === "true";
         sessionStorage.removeItem("mx_fresh_login");
@@ -605,7 +606,7 @@ export async function restoreSessionFromStorage(opts?: { ignoreGuest?: boolean }
             {
                 userId: userId,
                 deviceId: deviceId,
-                accessToken: decryptedAccessToken!,
+                accessToken: decryptedAccessToken,
                 refreshToken: decryptedRefreshToken,
                 homeserverUrl: hsUrl,
                 identityServerUrl: isUrl,
diff --git a/src/utils/tokens/tokens.ts b/src/utils/tokens/tokens.ts
index b6634171e076015e19f0da0db7b608ada993c852..a82259242aaaeb2e94aee06a6983635c18c498ab 100644
--- a/src/utils/tokens/tokens.ts
+++ b/src/utils/tokens/tokens.ts
@@ -68,10 +68,6 @@ async function pickleKeyToAesKey(pickleKey: string): Promise<Uint8Array> {
     );
 }
 
-const isEncryptedPayload = (token?: IEncryptedPayload | string | undefined): token is IEncryptedPayload => {
-    return !!token && typeof token !== "string";
-};
-
 /**
  * Try to decrypt a token retrieved from storage
  *
@@ -86,24 +82,27 @@ const isEncryptedPayload = (token?: IEncryptedPayload | string | undefined): tok
  * @param tokenName Name of the token. Used in logging, but also used as an input when generating the actual AES key,
  *    so the same value must be provided to {@link persistTokenInStorage}.
  *
- * @returns the decrypted token, or the plain text token. Returns undefined when token cannot be decrypted
+ * @returns the decrypted token, or the plain text token.
  */
 export async function tryDecryptToken(
     pickleKey: string | undefined,
-    token: IEncryptedPayload | string | undefined,
+    token: IEncryptedPayload | string,
     tokenName: string,
-): Promise<string | undefined> {
-    if (pickleKey && isEncryptedPayload(token)) {
-        const encrKey = await pickleKeyToAesKey(pickleKey);
-        const decryptedToken = await decryptAES(token, encrKey, tokenName);
-        encrKey.fill(0);
-        return decryptedToken;
-    }
-    // if the token wasn't encrypted (plain string) just return it back
+): Promise<string> {
     if (typeof token === "string") {
+        // Looks like an unencrypted token
         return token;
     }
-    // otherwise return undefined
+
+    // Otherwise, it must be an encrypted token.
+    if (!pickleKey) {
+        throw new Error(`Error decrypting secret ${tokenName}: no pickle key found.`);
+    }
+
+    const encrKey = await pickleKeyToAesKey(pickleKey);
+    const decryptedToken = await decryptAES(token, encrKey, tokenName);
+    encrKey.fill(0);
+    return decryptedToken;
 }
 
 /**
diff --git a/test/Lifecycle-test.ts b/test/Lifecycle-test.ts
index b0d044c10e0092521d15206eeaa43ef36286cc14..6ee6cb115409b0901528d1c90efdc03e78621293 100644
--- a/test/Lifecycle-test.ts
+++ b/test/Lifecycle-test.ts
@@ -145,7 +145,12 @@ describe("Lifecycle", () => {
                     mockStore[tableKey] = table;
                 },
             );
-        jest.spyOn(StorageAccess, "idbDelete").mockClear().mockResolvedValue(undefined);
+        jest.spyOn(StorageAccess, "idbDelete")
+            .mockClear()
+            .mockImplementation(async (tableKey: string, key: string | string[]) => {
+                const table = mockStore[tableKey];
+                delete table?.[key as string];
+            });
     };
 
     const homeserverUrl = "https://server.org";
@@ -521,6 +526,22 @@ describe("Lifecycle", () => {
 
                 expect(await restoreSessionFromStorage()).toEqual(true);
             });
+
+            it("should throw if the token was persisted with a pickle key but there is no pickle key available now", async () => {
+                initLocalStorageMock(localStorageSession);
+                initIdbMock({});
+
+                // Create a pickle key, and store it, encrypted, in IDB.
+                const pickleKey = (await PlatformPeg.get()!.createPickleKey(credentials.userId, credentials.deviceId))!;
+                localStorage.setItem("mx_has_pickle_key", "true");
+                await persistAccessTokenInStorage(credentials.accessToken, pickleKey);
+
+                // Now destroy the pickle key
+                await PlatformPeg.get()!.destroyPickleKey(credentials.userId, credentials.deviceId);
+
+                console.log("10");
+                expect(await restoreSessionFromStorage()).toEqual(true);
+            });
         });
     });