{"record":{"id":"1be8ecc24299fa4a","repo":"RocketChat/Rocket.Chat","slug":"accounts-changestoragebackend-failed","errorCode":null,"errorMessage":"[accounts] changeStorageBackend failed","messagePattern":"\\[accounts\\] changeStorageBackend failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/meteor/client/meteor/startup/accounts.ts","lineNumber":66,"sourceCode":"\t});\n};\n\nlet configuredStorageBackend: 'local' | 'session' = 'local';\n\nconst applyForgetSessionOnWindowClose = (): void => {\n\tconst forgetSession = Boolean(settings.peek<boolean>(FORGET_SESSION_SETTING_ID) ?? window[FORGET_SESSION_SETTING_ID]);\n\n\tconst storageBackend = forgetSession ? 'session' : 'local';\n\n\tif (configuredStorageBackend === storageBackend) {\n\t\treturn;\n\t}\n\n\twindow[FORGET_SESSION_SETTING_ID] = forgetSession;\n\ttry {\n\t\tgetDdpSdk().storage?.changeStorageBackend();\n\t} catch (error) {\n\t\tconsole.warn('[accounts] changeStorageBackend failed', error);\n\t\treturn;\n\t}\n\n\tconfiguredStorageBackend = storageBackend;\n};\n\napplyForgetSessionOnWindowClose();\nsettings.observe(FORGET_SESSION_SETTING_ID, applyForgetSessionOnWindowClose);\n\ngetDdpSdk().account.onEmailVerificationLink(async (token: string) => {\n\ttry {\n\t\tawait sdk.rest.post('/v1/users.verifyEmail', { token });\n\t\tawait whenMainReady();\n\t\tdispatchToastMessage({ type: 'success', message: t('Email_verified') });\n\t} catch (error) {\n\t\tawait whenMainReady();\n\t\tdispatchToastMessage({ type: 'error', message: error });\n\t\tthrow new Error('verify-email: E-mail not verified', { cause: error });","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2f18297792c973da326be7253f497d239ea6f2b0/apps/meteor/client/meteor/startup/accounts.ts#L48-L84","documentation":"When the Accounts_ForgetUserSessionOnClose ('forget session on window close') setting changes, the client switches the DDP SDK's credential storage between localStorage and sessionStorage via getDdpSdk().storage.changeStorageBackend(). If the storage module is unavailable or the swap throws (browser blocked storage, SecurityError in private mode, SDK not yet initialized), the call is caught, '[accounts] changeStorageBackend failed' is logged, and configuredStorageBackend is deliberately left unchanged so the previous backend keeps being used and the switch is retried on the next setting change.","triggerScenarios":"Toggling 'Forget session on window close' in admin settings while the browser blocks storage access (Safari ITP, strict privacy mode, site data disabled); the setting arriving before the SDK storage module is initialized at startup; embedded webviews without functioning localStorage.","commonSituations":"Privacy-hardened browsers or iframe embeddings where storage access throws SecurityError; races during app initialization; older SDK builds lacking changeStorageBackend support.","solutions":["Check the logged error - a SecurityError means the browser denied storage; have the user allow site data for the workspace domain","Reload after changing the setting: startup seeds the backend from the persisted window flag and applies the correct backend from the beginning","Ensure the DDP SDK is fully initialized before the setting observer fires (check for races in startup ordering)","Update @rocket.chat/ddp-client if the storage backend swap is unsupported in your SDK version"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const storageAvailable = (type: 'localStorage' | 'sessionStorage'): boolean => {\n\ttry {\n\t\tconst k = '__rc_probe__';\n\t\twindow[type].setItem(k, k);\n\t\twindow[type].removeItem(k);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\nif (!storageAvailable(forgetSession ? 'sessionStorage' : 'localStorage')) {\n\t// do not flip the backend; surface guidance instead of relying on the caught warn\n\tshowNotice('Storage blocked by browser - session persistence setting cannot apply');\n}","typeGuard":null,"tryCatchPattern":"try {\n\tgetDdpSdk().storage?.changeStorageBackend();\n} catch (error) {\n\t// backend intentionally unchanged; retry on next setting change - do not clear credentials here\n\tconsole.warn('[accounts] changeStorageBackend failed', error);\n}","preventionTips":["Probe storage availability before honoring forget-session toggles","Initialize the SDK storage before subscribing to the setting to avoid startup races","Test the forget-session flow in privacy modes (Safari ITP, incognito, iframes) where storage throws"],"tags":["console-warn","session-storage","local-storage","accounts","settings","client"],"backgroundTag":"web-storage-unavailable","analyzedSha":"2f18297792c973da326be7253f497d239ea6f2b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}