{"record":{"id":"9d41c907b024ce40","repo":"RocketChat/Rocket.Chat","slug":"403","errorCode":"403","errorMessage":"User validation failed","messagePattern":"User validation failed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":403,"severity":"error","filePath":"apps/meteor/server/lib/auth/startup.js","lineNumber":284,"sourceCode":"\t\t\tto: destinations,\n\t\t\tfrom: settings.get('From_Email'),\n\t\t\tsubject: Accounts.emailTemplates.userToActivate.subject(),\n\t\t\thtml: Accounts.emailTemplates.userToActivate.html({\n\t\t\t\t...options,\n\t\t\t\tname: options.name || options.profile?.name,\n\t\t\t\temail: options.email || user.emails[0].address,\n\t\t\t}),\n\t\t};\n\n\t\tawait Mailer.send(email);\n\t}\n\n\tif (!options.skipOnCreateUserCallback) {\n\t\tawait callbacks.run('onCreateUser', options, user);\n\t}\n\n\tif (!options.skipEmailValidation && !validateEmailDomain(user)) {\n\t\tthrow new Meteor.Error(403, 'User validation failed');\n\t}\n\n\treturn removeEmpty(user);\n};\n\nAccounts.onCreateUser(function (...args) {\n\t// Depends on meteor support for Async\n\treturn onCreateUserAsync.call(this, ...args);\n});\n\nconst { insertUserDoc } = Accounts;\n\nAccounts.insertUserDoc = async function (options, user) {\n\tconst globalRoles = new Set();\n\n\tif (Match.test(options.globalRoles, [String]) && options.globalRoles.length > 0) {\n\t\toptions.globalRoles.map((role) => globalRoles.add(role));\n\t}","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/auth/startup.js#L266-L302","documentation":"A 403 'User validation failed' raised in onCreateUserAsync when !validateEmailDomain(user) after the onCreateUser callback. In current code validateEmailDomain throws the more specific error-invalid-domain itself, so this branch acts as a legacy safety net for the same condition: the user's email domain is not accepted by Accounts_AllowedDomainsList, or a customized/older validateEmailDomain returned false instead of throwing.","triggerScenarios":"Any user-creation path with options.skipEmailValidation falsy where validateEmailDomain returns false or undefined instead of true — typically forked/monkey-patched validation code or older Rocket.Chat versions where the domain check returned false rather than throwing.","commonSituations":"Same misconfiguration as error-invalid-domain (whitelist too strict, subdomain not listed, programmatic imports); servers running customized auth startup code where validateEmailDomain behavior was changed.","solutions":["Fix Accounts_AllowedDomainsList exactly as for error-invalid-domain (add the exact domain or clear the setting)","Pass skipEmailValidation: true in options for trusted programmatic creation flows","If you maintain a fork, make your validateEmailDomain either return true or throw error-invalid-domain instead of returning false"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const isEmailAllowed = (email: string, whitelistSetting: string | undefined): boolean => {\n  const list = String(whitelistSetting ?? '').split(',').map((d) => d.trim()).filter(Boolean);\n  return list.length === 0 || list.some((d) => email.toLowerCase().endsWith('@' + d.toLowerCase()));\n};\n// pre-check before any programmatic user creation when the whitelist is set","typeGuard":null,"tryCatchPattern":"try {\n  await Accounts.createUserAsync(options);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 403 && /User validation failed/.test(String(e.reason ?? e.message))) {\n    // registration policy (domain whitelist) rejected the user: fix Accounts_AllowedDomainsList, do not retry\n  }\n  throw e;\n}","preventionTips":["Validate the email domain before every programmatic create (same check as error-invalid-domain)","If you customize validateEmailDomain, throw error-invalid-domain rather than returning false","Cover this path in tests for your auth customizations"],"tags":["authentication","user-registration","email-validation","legacy"],"backgroundTag":"user-registration-rejected","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}