diff --git a/lib/storage/index.ts b/lib/storage/index.ts index b4e80e74c..5c6313fff 100644 --- a/lib/storage/index.ts +++ b/lib/storage/index.ts @@ -20,7 +20,13 @@ type Storage = { * Degrade performance by removing the storage provider and only using cache */ function degradePerformance(error: Error) { - Logger.logHmmm(`Error while using ${provider.name}. Falling back to only using cache and dropping storage.\n Error: ${error.message}\n Stack: ${error.stack}\n Cause: ${error.cause}`); + let causeMessage = ''; + if (error.cause instanceof Error) { + causeMessage = error.cause.message; + } else if (typeof error.cause === 'string') { + causeMessage = error.cause; + } + Logger.logHmmm(`Error while using ${provider.name}. Falling back to only using cache and dropping storage.\n Error: ${error.message}\n Stack: ${error.stack}\n Cause: ${causeMessage}`); console.error(error); provider = MemoryOnlyProvider; } diff --git a/tests/unit/storage/tryOrDegradePerformanceTest.ts b/tests/unit/storage/tryOrDegradePerformanceTest.ts index b160b5903..de6f8c5a3 100644 --- a/tests/unit/storage/tryOrDegradePerformanceTest.ts +++ b/tests/unit/storage/tryOrDegradePerformanceTest.ts @@ -69,6 +69,24 @@ describe('storage/tryOrDegradePerformance', () => { expect(storage.getStorageProvider().name).toBe('MemoryOnlyProvider'); }); + it('serializes Error.cause as a readable string in the degrade log', async () => { + const {storage, Logger} = loadIsolatedStorage(); + const capturedLogs: CapturedLog[] = []; + Logger.registerLogger((data: LogData) => capturedLogs.push({level: data.level, message: data.message})); + + storage.init(); + + const originalProvider = storage.getStorageProvider(); + const targetError = new Error('IDBKeyVal store could not be created', {cause: new Error('underlying disk is full')}); + originalProvider.getAllKeys = jest.fn().mockReturnValue(Promise.reject(targetError)); + + await expect(storage.getAllKeys()).rejects.toBe(targetError); + + const degradeLog = capturedLogs.find((log) => log.level === 'hmmm' && log.message.includes('Falling back to only using cache')); + expect(degradeLog?.message).toContain('Cause: underlying disk is full'); + expect(degradeLog?.message).not.toContain('[object Object]'); + }); + it('propagates async rejections with unrelated messages without falling back', async () => { const {storage, Logger} = loadIsolatedStorage(); const capturedLogs: CapturedLog[] = [];