RocketChat/Rocket.Chat · error · Error
error-invalid-user
error-invalid-user
Error message
error-invalid-user
What it means
Thrown by the POST ldap.syncNow endpoint when this.userId is falsy. Because the route declares authRequired:true, the framework middleware should have rejected the request with 401 before the handler runs; reaching this throw indicates the auth context was lost or the route middleware was bypassed. It is effectively a defensive guard against a missing user session. Code is the raw string 'error-invalid-user' (plain Error, not Meteor.Error).
Source
Thrown at apps/meteor/ee/server/api/ldap.ts:32
required: ['message', 'success'],
additionalProperties: false,
});
API.v1.post(
'ldap.syncNow',
{
authRequired: true,
forceTwoFactorAuthenticationForNonEnterprise: true,
twoFactorRequired: true,
response: {
200: ldapSyncNowResponseSchema,
400: validateBadRequestErrorResponse,
401: validateUnauthorizedErrorResponse,
},
},
async function action() {
if (!this.userId) {
throw new Error('error-invalid-user');
}
if (!(await hasPermissionAsync(this.user, 'sync-auth-services-users'))) {
throw new Error('error-not-authorized');
}
if (settings.get('LDAP_Enable') !== true) {
throw new Error('LDAP_disabled');
}
await LDAPEnterprise.sync();
await LDAPEnterprise.syncAvatarAndAbacAttributes();
return API.v1.success({
message: 'Sync_in_progress' as const,
});
},
);View on GitHub (pinned to f9d3ec372b)
Solutions
- Authenticate the request: send a valid X-Auth-Token + X-User-Id header (or resume token) so the framework populates this.userId.
- If testing, seed this.userId on the request context before invoking the action.
- Audit any custom middleware on the ldap.syncNow route that could clear this.user.
- Confirm the API framework version correctly runs authRequired before the action.
Example fix
// before (test): handler invoked with no user context
await action.call({});
// after: seed userId on the bound context
await action.call({ userId: 'rocketchat.internal.admin.test', user: adminUser }); Defensive patterns
Strategy: validation
Validate before calling
// Ensure auth context is present before invoking the handler (e.g. in tests)
function assertUserId(ctx: { userId?: string }): asserts ctx is { userId: string } {
if (!ctx.userId) throw new Error('error-invalid-user');
}
assertUserId(this); Type guard
function hasUserId(ctx: unknown): ctx is { userId: string; user: unknown } {
return typeof ctx === 'object' && ctx !== null && typeof (ctx as any).userId === 'string';
} Try / catch
try {
await api.post('ldap.syncNow', {});
} catch (e) {
if (e.message === 'error-invalid-user') {
// re-authenticate, then retry once
await relogin();
return api.post('ldap.syncNow', {});
}
throw e;
} Prevention
- Always send valid X-Auth-Token + X-User-Id headers on protected endpoints.
- In tests, seed this.userId on the bound action context.
When it happens
Trigger: Calling POST /v1/ldap.syncNow with a missing/invalid auth token that somehow passed the authRequired gate, or invoking the action function outside the normal API middleware pipeline (e.g. direct unit test without seeding this.userId).
Common situations: Token expired between auth middleware and handler in a long-lived request; test harness calling the handler directly without mocking this.userId; custom middleware that strips the user object.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/6fd002a6700b9af2.
Report an issue: GitHub.