RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
The optional "userId" param provided does not match any users
What it means
Thrown by POST users.setPreferences when the resolved target userId matches no user document. After the permission check, the endpoint does a Users.findOneById on the passed userId (or the caller's own id) and requires a hit before saving preferences.
Solutions
- Verify the id first with GET users.info?userId=... — if that 404s/fails, fix the reference
- For self-edits, omit userId so the server uses the authenticated id
- Refresh your user cache when this fires rather than retrying the same id
Example fix
// before
await sdk.post('users.setPreferences', { userId, data }); // userId from stale cache
// after
const info = await sdk.get('users.info', { userId });
if (!info.user) throw new Error('unknown target user');
await sdk.post('users.setPreferences', { userId, data }); Defensive patterns
Strategy: validation
Validate before calling
if (targetUserId) {
const { users } = await sdk.get('users.list', {}).catch(() => ({ users: [] }));
if (targetUserId !== myUserId && !users.some((u) => u._id === targetUserId)) throw new Error('target user does not exist');
} Try / catch
catch (e) { if (e?.error === 'error-invalid-user') refreshUserReferences(); else throw e; } Prevention
- Verify user ids with users.info before mutating them
- Drop stale user references from client caches on this error
When it happens
Trigger: POST with {userId: 'nonExistentOrDeletedId', ...}; userId with a stray space or wrong casing/copy-paste artifact; the caller's own account deleted between token issuance and the call (token still resolves to a dead user id).
Common situations: Stale user references in client state after account deletion; tools importing user lists where an id column is off by one character; race with account deletion during an active session.
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- error-action-not-allowed
- error-invalid-query
- error-user-param-not-provided
- Emoji not found.
- error-bio-size-exceeded
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-21).
Data as JSON: /api/errors/5bf8135809165cb4.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/users.ts:250
authRequired: true,
body: isUsersSetPreferencesParamsPOST,
response: {
200: userObjectResponse,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
},
},
async function action() {
if (
this.bodyParams.userId &&
this.bodyParams.userId !== this.userId &&
!(await hasPermissionAsync(this.user, 'edit-other-user-info'))
) {
throw new Meteor.Error('error-action-not-allowed', 'Editing user is not allowed');
}
const userId = this.bodyParams.userId ? this.bodyParams.userId : this.userId;
if (!(await Users.findOneById(userId))) {
throw new Meteor.Error('error-invalid-user', 'The optional "userId" param provided does not match any users');
}
const { statusVisibilityDenied: _ownBlockList, ...preferences } = this.bodyParams.data;
await saveUserPreferences(userId === this.userId ? this.bodyParams.data : preferences, userId);
const user = await Users.findOneById(userId, {
projection: {
'settings.preferences': 1,
'language': 1,
},
});
if (!user) {
return API.v1.failure('User not found');
}
const { statusVisibilityDenied, ...savedPreferences } = user.settings?.preferences ?? {};
View on GitHub (pinned to e4b8178b20)