{"record":{"id":"97ce75f20986f960","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-97ce75","errorCode":"error-invalid-user","errorMessage":"The required \"userId\" or \"username\" param provided does not match any users","messagePattern":"The required \"userId\" or \"username\" param provided does not match any users","errorType":"validation","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/lib/getUserFromParams.ts","lineNumber":35,"sourceCode":"\t\t: Pick<IUser, '_id' | 'username' | 'name' | 'status' | 'statusDefault' | 'statusText' | 'statusSource' | 'statusExpiresAt' | 'roles'>\n> {\n\tlet user;\n\n\tconst projection = full\n\t\t? {}\n\t\t: { username: 1, name: 1, status: 1, statusDefault: 1, statusText: 1, statusSource: 1, statusExpiresAt: 1, roles: 1 };\n\tif (params.userId?.trim()) {\n\t\tuser = await Users.findOneById(params.userId, { projection });\n\t} else if (params.username?.trim()) {\n\t\tuser = await Users.findOneByUsernameIgnoringCase(params.username, { projection });\n\t} else if (params.user?.trim()) {\n\t\tuser = await Users.findOneByUsernameIgnoringCase(params.user, { projection });\n\t} else {\n\t\tthrow new Meteor.Error('error-user-param-not-provided', 'The required \"userId\" or \"username\" param was not provided');\n\t}\n\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'The required \"userId\" or \"username\" param provided does not match any users');\n\t}\n\n\treturn user;\n}\n\nexport async function getUserListFromParams(params: {\n\tuserId?: string;\n\tusername?: string;\n\tuser?: string;\n\tuserIds?: string[];\n\tusernames?: string[];\n}): Promise<Pick<IUser, '_id' | 'username'>[]> {\n\t// if params.userId is provided, include it as well\n\tconst soleUser = params.userId || params.username || params.user;\n\tlet userListParam = params.userIds || params.usernames || [];\n\tuserListParam.push(soleUser || '');\n\tuserListParam = userListParam.filter(Boolean);\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/lib/getUserFromParams.ts#L17-L53","documentation":"Thrown by getUserFromParams, the shared REST v1 helper that resolves a user from request params. Params are checked in priority order: userId (exact _id lookup), then username, then user (both case-insensitive username lookups). If one param was supplied but no user document matches it, the helper throws error-invalid-user. This is a 'value supplied but nothing found' error, distinct from error-user-param-not-provided which fires when no param is given at all.","triggerScenarios":"Calling any REST v1 endpoint backed by this helper (users.info-style flows in apps/meteor/server/api/v1/{users,channels,groups,rooms,misc,roles}.ts) with a userId that is not a real user _id, or a username/user value that matches no username. Typical: passing the username 'rocket.cat' inside the userId param (it is then looked up as an _id and fails), quoting the ID with stray whitespace, or referencing a user that was deleted.","commonSituations":"Client cached a stale userId across a workspace reset or user deletion; copy-pasting a username where an _id belongs; federation setups where the user exists on another server but not locally; renamed users when the old username was stored.","solutions":["Verify the user exists first with GET /api/v1/users.info?username=<value> (or ?userId=) to see which identifier resolves","Make sure usernames go into the username or user param and Mongo _ids into userId — userId is matched by _id only, not by name","Trim and URL-decode the value; check for invisible characters or broken JSON encoding in the query string","If the user was deleted or lives on a federated server, re-create/resolve the account or use its local username"],"exampleFix":"// before\nGET /api/v1/users.info?userId=rocket.cat   // username wrongly used as _id\n\n// after\nGET /api/v1/users.info?username=rocket.cat // or ?userId=aobEdbYhXfu5hkeqG","handlingStrategy":"validation","validationCode":"async function resolveUserIdent(client, userIdOrName: string): Promise<string> {\n  // users.info accepts either param and 404s cleanly when absent\n  const r = await client.get('/api/v1/users.info', { params: { userId: userIdOrName } });\n  if (r.ok) return r.data.user._id;\n  const byName = await client.get('/api/v1/users.info', { params: { username: userIdOrName } });\n  if (byName.ok) return byName.data.user._id;\n  throw new Error(`no user matches ${userIdOrName}`);\n}","typeGuard":"const isUserRef = (v: unknown): v is { userId?: string; username?: string; user?: string } =>\n  typeof v === 'object' && v !== null && !Array.isArray(v) &&\n  Object.values(v).some((x) => typeof x === 'string' && x.trim() !== '');","tryCatchPattern":"try {\n  await client.get('/api/v1/channels.info', { params: { username } });\n} catch (e: any) {\n  if (e?.response?.data?.errorType === 'error-invalid-user') {\n    // treat as 404: identifier valid but no such user\n    throw new NotFoundError(`user ${username} not found`);\n  }\n  throw e;\n}","preventionTips":["Normalize all user references to _id at ingestion time and store the source of the identifier","Never put a username into the userId param — userId is matched by _id only","Wrap user-dependent calls with a users.info existence probe when identifiers come from user input or stale caches"],"tags":["rest-api","user-lookup","invalid-param","meteor-error"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}