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
- Validate that keyPair has non-empty snake_case string fields public_key and private_key before invoking the method.
- On the client, await full key-pair generation and confirm the exported PEM/base64 strings are non-empty before calling.
- If local E2E storage is corrupted, clear the client's stored e2e keys and restart the key-generation flow.
- 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
- Await key-pair generation fully before persisting keys.
- Never hand-build the keyPair object; use the generator's exact snake_case output.
- Log the exported key lengths (not contents) during E2EE onboarding to catch empty exports early.
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
- Failed to persist keys as they are not strings.
- Failed to encode private key with provided password.
- error-e2e-enabled
- error-invalid-command
- error-invalid-arguments
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/24ce5eadbf1b35ac.
Report an issue: GitHub.