RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-user
error-invalid-user
Error message
Invalid user
What it means
addOAuthApp() backs POST /api/v1/oauth-apps.create (and the equivalent method). It refuses to operate when uid is falsy: no user context means no audit trail or permission anchor for the new OAuth app. The REST route is authRequired and permissionsRequired, so this specific throw is reachable mainly from direct/internal calls (server code, apps, tests) that pass an undefined user id.
Source
Thrown at apps/meteor/server/lib/auth/oauth2-server/addOAuthApp.ts:12
import type { IOAuthApps, IUser } from '@rocket.chat/core-typings';
import { OAuthApps, Users } from '@rocket.chat/models';
import { Random } from '@rocket.chat/random';
import { Meteor } from 'meteor/meteor';
import { parseUriList } from './parseUriList';
import type { OauthAppsAddParams } from '../../../api/v1/oauthapps';
import { hasPermissionAsync } from '../../authorization/hasPermission';
export async function addOAuthApp(applicationParams: OauthAppsAddParams, uid: IUser['_id'] | undefined): Promise<IOAuthApps> {
if (!uid) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'addOAuthApp' });
}
const user = await Users.findOneById(uid, { projection: { username: 1 } });
if (!user?.username) {
// TODO: username is required, but not always present
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'addOAuthApp' });
}
if (!(await hasPermissionAsync(uid, 'manage-oauth-apps'))) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'addOAuthApp' });
}
if (!applicationParams.name || typeof applicationParams.name.valueOf() !== 'string' || applicationParams.name.trim() === '') {
throw new Meteor.Error('error-invalid-name', 'Invalid name', { method: 'addOAuthApp' });
}
if (View on GitHub (pinned to b2c16d5842)
Solutions
- Pass the authenticated user's _id as uid, e.g. addOAuthApp(params, Meteor.userId()) or this.userId in a method
- Prefer the REST endpoint POST /api/v1/oauth-apps.create with an auth token - it guarantees a uid and permission check
- Guard the call site: return early with a proper authentication error when uid is undefined
Example fix
// before
await addOAuthApp(params, undefined);
// after
const uid = Meteor.userId();
if (!uid) throw new Meteor.Error('error-not-logged-in', 'Must be logged in');
await addOAuthApp(params, uid); Defensive patterns
Strategy: validation
Validate before calling
// guard the call site before invoking
const uid = Meteor.userId();
if (!uid) {
throw new Meteor.Error('error-not-logged-in', 'Must be logged in to create OAuth apps');
}
const app = await addOAuthApp(params, uid); Type guard
const hasAuthenticatedUid = (uid: string | undefined): uid is string => typeof uid === 'string' && uid.length > 0;
Try / catch
try {
await addOAuthApp(params, uid);
} catch (error) {
if (error instanceof Meteor.Error && error.error === 'error-invalid-user') {
throw new Meteor.Error('error-not-logged-in', 'Authentication required');
}
throw error;
} Prevention
- Always derive uid from the authenticated context (this.userId / Meteor.userId()), never from request bodies
- Prefer the REST endpoint, which enforces authentication for you
- In tests, seed a user fixture and pass its _id
When it happens
Trigger: Calling addOAuthApp(params, undefined) from server code; a method wrapper that forwards this.userId of an unauthenticated context; tests invoking the function without a user id.
Common situations: Custom integrations or Apps calling the library function directly instead of the REST endpoint; refactors that drop the uid argument; unit tests missing a user fixture.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/3ea910ee590f8ce8.
Report an issue: GitHub.