RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-keys

error-invalid-keys

Error message

Invalid keys

What it means

Thrown by the 'e2e.setUserPublicAndPrivateKeys' Meteor method when the keyPair argument lacks a truthy public_key or private_key field. Rocket.Chat calls this once per user during end-to-end-encryption setup to persist the generated RSA key pair. The guard is a plain truthiness check, so missing fields, empty strings, null, or undefined in either slot are rejected before setUserPublicAndPrivateKeysMethod runs. The method is deprecated since 9.0.0 in favor of POST /v1/e2e.setUserPublicAndPrivateKeys.

Source

Thrown at apps/meteor/server/meteor-methods/platform/setUserPublicAndPrivateKeys.ts:56

	const subscribedRoomIds = await Rooms.getSubscribedRoomIdsWithoutE2EKeys(userId);
	await Rooms.addUserIdToE2EEQueueByRoomIds(subscribedRoomIds, userId);

	void notifyOnRoomChangedById(subscribedRoomIds);
};

Meteor.methods<ServerMethods>({
	async 'e2e.setUserPublicAndPrivateKeys'(keyPair) {
		methodDeprecationLogger.method('e2e.setUserPublicAndPrivateKeys', '9.0.0', '/v1/e2e.setUserPublicAndPrivateKeys');
		const userId = Meteor.userId();

		if (!userId) {
			throw new Meteor.Error('error-invalid-user', 'Invalid user', {
				method: 'e2e.setUserPublicAndPrivateKeys',
			});
		}

		if (!keyPair.public_key || !keyPair.private_key) {
			throw new Meteor.Error('error-invalid-keys', 'Invalid keys', {
				method: 'e2e.setUserPublicAndPrivateKeys',
			});
		}

		await setUserPublicAndPrivateKeysMethod(userId, keyPair);
	},
});

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Validate that keyPair has non-empty snake_case string fields public_key and private_key before invoking the method.
  2. On the client, await full key-pair generation and confirm the exported PEM/base64 strings are non-empty before calling.
  3. If local E2E storage is corrupted, clear the client's stored e2e keys and restart the key-generation flow.
  4. On migrated servers, confirm the REST equivalent /v1/e2e.setUserPublicAndPrivateKeys receives the same payload shape.

Example fix

// before
Meteor.callAsync('e2e.setUserPublicAndPrivateKeys', keyPair);

// after
if (!keyPair?.public_key || !keyPair?.private_key) {
	throw new Error('E2E key pair incomplete - regenerate before saving');
}
await Meteor.callAsync('e2e.setUserPublicAndPrivateKeys', keyPair);
Defensive patterns

Strategy: validation

Validate before calling

const hasValidKeyPair = (kp: { public_key?: unknown; private_key?: unknown }): boolean =>
	typeof kp?.public_key === 'string' && (kp.public_key as string).length > 0 &&
	typeof kp?.private_key === 'string' && (kp.private_key as string).length > 0;

if (!hasValidKeyPair(keyPair)) {
	throw new Error('E2E key pair incomplete - regenerate keys before saving');
}
await Meteor.callAsync('e2e.setUserPublicAndPrivateKeys', keyPair);

Type guard

interface E2EKeyPair { public_key: string; private_key: string }
function isE2EKeyPair(v: unknown): v is E2EKeyPair {
	if (typeof v !== 'object' || v === null) return false;
	const kp = v as Record<string, unknown>;
	return typeof kp.public_key === 'string' && kp.public_key.length > 0 &&
		typeof kp.private_key === 'string' && kp.private_key.length > 0;
}

Try / catch

try {
	await Meteor.callAsync('e2e.setUserPublicAndPrivateKeys', keyPair);
} catch (e: any) {
	if (e?.error === 'error-invalid-keys') {
		// regenerate the pair client-side, then retry once
	}
}

Prevention

When it happens

Trigger: Calling Meteor.callAsync('e2e.setUserPublicAndPrivateKeys', keyPair) where keyPair.public_key or keyPair.private_key is missing/empty/undefined - typically because the browser's RSA key-pair generation failed or had not finished before the call, or the client built the object with wrong field names (publicKey instead of public_key).

Common situations: E2EE setup races where the method fires before key generation completes; corrupted or wiped local E2E key storage; custom clients or tests hand-crafting the keyPair payload; key export returning an empty string after subprocess/browser quirks.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/24ce5eadbf1b35ac. Report an issue: GitHub.