RocketChat/Rocket.Chat · error · Error

E2E encryption can only be enabled in secure contexts (HTTPS

Error message

E2E encryption can only be enabled in secure contexts (HTTPS)

What it means

Thrown by the E2E (end-to-end encryption) client's startClient method when the browser's isSecureContext flag is false. isSecureContext is a Web API that is true only when the page is served over HTTPS (or is localhost/127.0.0.1). E2E encryption relies on the Web Crypto API (specifically crypto.subtle), which is only available in secure contexts, so the client refuses to initialize without it.

Source

Thrown at apps/meteor/client/lib/e2ee/rocketchat.e2e.ts:347

				onClose: imperativeModal.close,
				onCancel: () => {
					this.closeAlert();
					imperativeModal.close();
				},
				onConfirm: () => {
					removeStoredItem(STORAGE_KEYS.E2EE_RANDOM_PASSWORD);
					this.setState('READY');
					dispatchToastMessage({ type: 'success', message: t('E2E_encryption_enabled') });
					this.closeAlert();
					imperativeModal.close();
				},
			},
		});
	}

	async startClient(userId: string): Promise<void> {
		if (!isSecureContext) {
			throw new Error('E2E encryption can only be enabled in secure contexts (HTTPS)');
		}

		const span = log.span('startClient');
		if (this.userId === userId) {
			return;
		}

		span.info(this.state);

		this.userId = userId;
		this.keychain = new Keychain(userId);

		let { public_key, private_key } = this.getKeysFromLocalStorage();

		await this.loadKeysFromDB();

		if (!public_key && this.db_public_key) {
			public_key = this.db_public_key;

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Serve the Rocket.Chat client over HTTPS (configure TLS on the server or use a TLS-terminating reverse proxy).
  2. For local development, use http://localhost or http://127.0.0.1 — these are treated as secure contexts by browsers.
  3. If behind a reverse proxy (nginx, Traefik), ensure X-Forwarded-Proto: https is passed and ROOT_URL is set to https://.
  4. Disable E2E if HTTPS is not available and encryption is not required for the deployment.

Example fix

// before: served over http://chat.example.com
// after: configure TLS
// nginx config:
// listen 443 ssl;
// proxy_set_header X-Forwarded-Proto https;
// ROOT_URL=https://chat.example.com
Defensive patterns

Strategy: validation

Validate before calling

if (!window.isSecureContext) {
  // show user-facing error: HTTPS required for E2E
  showE2ESecureContextError();
  return;
}
await e2e.startClient(userId);

Type guard

const isSecureContextAvailable = (): boolean => typeof window !== 'undefined' && window.isSecureContext === true;

Try / catch

try {
  await e2e.startClient(userId);
} catch (e) {
  if (e instanceof Error && e.message.includes('secure context')) {
    dispatchToastMessage({ type: 'error', message: t('E2E_requires_https') });
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: The Rocket.Chat web client is served over plain HTTP (not HTTPS) and the hostname is not localhost. The app is loaded in an insecure iframe. A proxy or load balancer terminates TLS but the app origin is misconfigured as http://. Service worker or non-secure origin context.

Common situations: Self-hosted development/staging server without TLS configured. Behind a reverse proxy where X-Forwarded-Proto is not set correctly, so the Node server thinks it is HTTP. Using an IP address instead of localhost over plain HTTP. Migration from HTTP to HTTPS that left the ROOT_URL as http://.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/e632a531b01b600f. Report an issue: GitHub.