{"record":{"id":"4ac0ea867ce9d2ff","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-email-4ac0ea","errorCode":"error-invalid-email","errorMessage":"Invalid email","messagePattern":"Invalid email","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/users/setEmail.ts","lineNumber":58,"sourceCode":"\t\t});\n\t}\n};\n\nexport const setEmail = async function (\n\tuserId: string,\n\temail: string,\n\tshouldSendVerificationEmail = true,\n\tverified = false,\n\tupdater?: Updater<IUser>,\n\tsession?: ClientSession,\n) {\n\temail = email.trim();\n\tif (!userId) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { function: '_setEmail' });\n\t}\n\n\tif (!email) {\n\t\tthrow new Meteor.Error('error-invalid-email', 'Invalid email', { function: '_setEmail' });\n\t}\n\n\tawait validateEmailDomain(email);\n\n\tconst user = await Users.findOneById(userId, { session });\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { function: '_setEmail' });\n\t}\n\n\t// User already has desired username, return\n\tif (user?.emails?.[0] && user.emails[0].address === email) {\n\t\treturn user;\n\t}\n\n\t// Check email availability\n\tif (!(await checkEmailAvailability(email))) {\n\t\tthrow new Meteor.Error('error-field-unavailable', `${email} is already in use :(`, {\n\t\t\tfunction: '_setEmail',","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/users/setEmail.ts#L40-L76","documentation":"setEmail trims the email argument and throws error-invalid-email when the result is empty. This is pure presence validation: it fires before domain validation (validateEmailDomain) and availability checks, and no email-format regex runs here. Only an empty or whitespace-only string reaches this branch.","triggerScenarios":"setEmail(userId, '') or setEmail(userId, '   ') — a form submitted with a blank email field, an optional field mapped straight into the call, or null coerced to empty string.","commonSituations":"Admin UI allowing blank email submissions; JSON payload with \"email\": \"\"; copy-paste whitespace-only values; migration scripts writing '' for users with no address.","solutions":["Require a non-empty, trimmed email in the calling form/API layer before invoking setEmail.","Add basic format validation (regex) client-side so blank/garbage input never reaches the server.","If email is optional in your flow, skip the setEmail call entirely instead of passing an empty string."],"exampleFix":"// before\nawait setEmail(userId, req.body.email || '');\n\n// after\nconst email = (req.body.email ?? '').trim();\nif (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email)) {\n  throw new Meteor.Error('error-invalid-email', 'Invalid email');\n}\nawait setEmail(userId, email);","handlingStrategy":"validation","validationCode":"const email = (rawEmail ?? '').trim();\nif (!/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(email)) {\n  throw new Meteor.Error('error-invalid-email', 'Invalid email', { field: 'email' });\n}\nawait setEmail(userId, email);","typeGuard":"const isValidEmail = (value: string): boolean => /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(value.trim());","tryCatchPattern":null,"preventionTips":["Make the email field required in forms that feed setEmail.","Trim user input before submission.","Validate format client-side and server-side; never rely on the UI alone."],"tags":["validation","email","forms"],"backgroundTag":"email-validation-failed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}