RocketChat/Rocket.Chat · warning

[accounts] changeStorageBackend failed

Error message

[accounts] changeStorageBackend failed

What it means

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.

Source

Thrown at apps/meteor/client/meteor/startup/accounts.ts:66

	});
};

let configuredStorageBackend: 'local' | 'session' = 'local';

const applyForgetSessionOnWindowClose = (): void => {
	const forgetSession = Boolean(settings.peek<boolean>(FORGET_SESSION_SETTING_ID) ?? window[FORGET_SESSION_SETTING_ID]);

	const storageBackend = forgetSession ? 'session' : 'local';

	if (configuredStorageBackend === storageBackend) {
		return;
	}

	window[FORGET_SESSION_SETTING_ID] = forgetSession;
	try {
		getDdpSdk().storage?.changeStorageBackend();
	} catch (error) {
		console.warn('[accounts] changeStorageBackend failed', error);
		return;
	}

	configuredStorageBackend = storageBackend;
};

applyForgetSessionOnWindowClose();
settings.observe(FORGET_SESSION_SETTING_ID, applyForgetSessionOnWindowClose);

getDdpSdk().account.onEmailVerificationLink(async (token: string) => {
	try {
		await sdk.rest.post('/v1/users.verifyEmail', { token });
		await whenMainReady();
		dispatchToastMessage({ type: 'success', message: t('Email_verified') });
	} catch (error) {
		await whenMainReady();
		dispatchToastMessage({ type: 'error', message: error });
		throw new Error('verify-email: E-mail not verified', { cause: error });

View on GitHub (pinned to 2f18297792)

Solutions

  1. Check the logged error - a SecurityError means the browser denied storage; have the user allow site data for the workspace domain
  2. Reload after changing the setting: startup seeds the backend from the persisted window flag and applies the correct backend from the beginning
  3. Ensure the DDP SDK is fully initialized before the setting observer fires (check for races in startup ordering)
  4. Update @rocket.chat/ddp-client if the storage backend swap is unsupported in your SDK version
Defensive patterns

Strategy: validation

Validate before calling

const storageAvailable = (type: 'localStorage' | 'sessionStorage'): boolean => {
	try {
		const k = '__rc_probe__';
		window[type].setItem(k, k);
		window[type].removeItem(k);
		return true;
	} catch {
		return false;
	}
};

if (!storageAvailable(forgetSession ? 'sessionStorage' : 'localStorage')) {
	// do not flip the backend; surface guidance instead of relying on the caught warn
	showNotice('Storage blocked by browser - session persistence setting cannot apply');
}

Try / catch

try {
	getDdpSdk().storage?.changeStorageBackend();
} catch (error) {
	// backend intentionally unchanged; retry on next setting change - do not clear credentials here
	console.warn('[accounts] changeStorageBackend failed', error);
}

Prevention

When it happens

Trigger: 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.

Common situations: Privacy-hardened browsers or iframe embeddings where storage access throws SecurityError; races during app initialization; older SDK builds lacking changeStorageBackend support.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@2f18297792 (2026-08-18). Data as JSON: /api/errors/1be8ecc24299fa4a. Report an issue: GitHub.