{"record":{"id":"2ed00fceb8209cc8","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-2ed00f","errorCode":"error-invalid-user","errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/users/saveNotificationSettings.ts","lineNumber":41,"sourceCode":"\t| 'audioNotificationValue';\ndeclare module '@rocket.chat/ddp-client' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention\n\tinterface ServerMethods {\n\t\tsaveNotificationSettings(roomId: string, field: NotificationFieldType, value: string): boolean;\n\t\tsaveAudioNotificationValue(subId: string, value: string): boolean;\n\t}\n}\n\nexport const saveNotificationSettingsMethod = async (\n\tuserId: string,\n\troomId: string,\n\tfield: NotificationFieldType,\n\tvalue: string,\n): Promise<boolean> => {\n\tconst getNotificationPrefValue = async (field: string, value: unknown) => {\n\t\tif (value === 'default') {\n\t\t\tif (!userId) {\n\t\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\t\tmethod: 'saveNotificationSettings',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst userPref = await getUserNotificationPreference(userId, field);\n\t\t\treturn userPref?.origin === 'server' ? null : userPref;\n\t\t}\n\t\treturn { value, origin: 'subscription' };\n\t};\n\n\tconst notifications = {\n\t\tdesktopNotifications: {\n\t\t\tupdateMethod: async (subscription: ISubscription, value: unknown) =>\n\t\t\t\tSubscriptions.updateNotificationsPrefById(\n\t\t\t\t\tsubscription._id,\n\t\t\t\t\tawait getNotificationPrefValue('desktop', value),\n\t\t\t\t\t'desktopNotifications',\n\t\t\t\t\t'desktopPrefOrigin',","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/users/saveNotificationSettings.ts#L23-L59","documentation":"Thrown inside saveNotificationSettingsMethod's helper getNotificationPrefValue when the requested value is 'default' and the userId param is empty. Resolving 'default' requires reading the caller's server-level user preference, which is impossible without a user; the code guards that with 'error-invalid-user'. The exported method receives userId from its callers, so this fires when it is invoked with a falsy user id (unauthenticated DDP call or a server-side caller passing '').","triggerScenarios":"Meteor.call('saveNotificationSettings', roomId, 'desktopNotifications', 'default') while logged out (wrapper passes Meteor.userId() = null downstream in older paths); server code importing saveNotificationSettingsMethod and passing an empty userId with value 'default'.","commonSituations":"Preference panels that submit 'default' after session expiry; background jobs reusing the method without a user context.","solutions":["Authenticate before calling: ensure Meteor.userId() is set (or pass a real user id to the exported method).","In server code, skip the call when no user context exists instead of passing '' as userId.","Use the REST endpoint POST /v1/rooms.saveNotification with valid auth credentials."],"exampleFix":"// before: fires after logout because value is 'default' and userId is falsy\nawait saveNotificationSettingsMethod('', rid, 'desktopNotifications', 'default');\n\n// after: only resolve 'default' with a real user; otherwise store the literal value\nif (value === 'default' && !userId) throw new Meteor.Error('error-invalid-user', 'Invalid user');\nawait saveNotificationSettingsMethod(userId, rid, 'desktopNotifications', value);","handlingStrategy":"type-guard","validationCode":"const uid = Meteor.userId();\nconst safeValue = uid ? value : (value === 'default' ? 'all' : value);\n// or skip the call entirely when resolving 'default' is impossible:\nif (value === 'default' && !uid) return showError('Log in to use default preferences');\nawait Meteor.callAsync('saveNotificationSettings', rid, field, value);","typeGuard":"const hasUserContext = (userId: string | null | undefined): userId is string =>\n  typeof userId === 'string' && userId.length > 0;","tryCatchPattern":"try {\n  await saveNotificationSettingsMethod(userId, rid, field, value);\n} catch (e) {\n  if ((e as Meteor.Error).error === 'error-invalid-user' && value === 'default') {\n    // resolving 'default' needs a user; fall back to an explicit value\n    await saveNotificationSettingsMethod(userId, rid, field, 'all');\n  }\n}","preventionTips":["Never invoke saveNotificationSettingsMethod with an empty userId and value 'default'","Resolve 'default' to a concrete value when no user context exists","Keep the method wrapper's Meteor.userId() guard as the single source of the user id"],"tags":["notifications","authentication","meteor-method","preferences"],"backgroundTag":"user-not-authenticated","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}