RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
Thrown by the 'e2e.getUsersOfRoomWithoutKey' method wrapper when the DDP connection has no authenticated user. The wrapper resolves Meteor.userId() before any room validation; a null uid aborts the E2E public-key request before room access is even evaluated.
Source
Thrown at apps/meteor/server/meteor-methods/platform/getUsersOfRoomWithoutKey.ts:43
projection: { 'u._id': 1 },
}).toArray();
const userIds = subscriptions.map((s) => s.u._id);
const options = { projection: { 'e2e.public_key': 1 } };
const users = await Users.findByIdsWithPublicE2EKey(userIds, options).toArray();
return {
users,
};
};
Meteor.methods<ServerMethods>({
async 'e2e.getUsersOfRoomWithoutKey'(rid) {
check(rid, String);
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'e2e.getUsersOfRoomWithoutKey',
});
}
if (!rid) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'e2e.getUsersOfRoomWithoutKey',
});
}
return getUsersOfRoomWithoutKeyMethod(userId, rid);
},
});
View on GitHub (pinned to b2c16d5842)
Solutions
- Re-authenticate and restart the E2E key exchange
- Guard the call with Meteor.userId() before requesting room member keys
- Sequence the handshake to start only after the user session is confirmed
Example fix
// before
const { users } = await Meteor.callAsync('e2e.getUsersOfRoomWithoutKey', rid);
// after
if (!Meteor.userId()) {
return restartE2EHandshakeAfterLogin();
}
const { users } = await Meteor.callAsync('e2e.getUsersOfRoomWithoutKey', rid); Defensive patterns
Strategy: validation
Validate before calling
// client: E2E member-key requests require a session
if (!Meteor.userId()) {
// defer the handshake until after login
} Type guard
import { Meteor } from 'meteor/meteor';
const isMeteorError = (err: unknown, code?: string): err is Meteor.Error =>
err instanceof Meteor.Error && (code === undefined || err.error === code); Try / catch
try {
const { users } = await Meteor.callAsync('e2e.getUsersOfRoomWithoutKey', rid);
} catch (err) {
if (isMeteorError(err, 'error-invalid-user')) {
// re-authenticate, then restart the key exchange
} else {
throw err;
}
} Prevention
- Start E2E handshakes only after the user session is confirmed
- Centralize session checks in the E2E flow's entry points
When it happens
Trigger: Running the E2E key handshake from an expired or logged-out session; calling the method during login/logout transitions; automated E2E tests without a seeded user session.
Common situations: Token expiry in long-lived clients during encrypted-room setup; components resuming E2E handshakes before user state loads.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/d51155c22b63121a.
Report an issue: GitHub.