{"record":{"id":"1bf8da1278797043","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-domain","errorCode":"error-invalid-domain","errorMessage":"error-invalid-domain","messagePattern":"error-invalid-domain","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/auth/startup.js","lineNumber":205,"sourceCode":"\nconst validateEmailDomain = (user) => {\n\tif (user.type === 'visitor') {\n\t\treturn true;\n\t}\n\n\tlet domainWhiteList = settings.get('Accounts_AllowedDomainsList');\n\tif (_.isEmpty(domainWhiteList?.trim())) {\n\t\treturn true;\n\t}\n\n\tdomainWhiteList = domainWhiteList.split(',').map((domain) => domain.trim());\n\n\tif (user.emails && user.emails.length > 0) {\n\t\tconst email = user.emails[0].address;\n\t\tconst inWhiteList = domainWhiteList.some((domain) => email.match(`@${escapeRegExp(domain)}$`));\n\n\t\tif (!inWhiteList) {\n\t\t\tthrow new Meteor.Error('error-invalid-domain');\n\t\t}\n\t}\n\n\treturn true;\n};\n\nconst onCreateUserAsync = async function (options, user = {}) {\n\tif (!options.skipBeforeCreateUserCallback) {\n\t\tawait beforeCreateUserCallback.run(options, user);\n\t}\n\tuser.status = 'offline';\n\n\tuser.active = user.active !== undefined ? user.active : !settings.get('Accounts_ManuallyApproveNewUsers');\n\tif (settings.get('Accounts_ManuallyApproveNewUsers') && !user.active) {\n\t\tuser.inactiveReason = 'pending_approval';\n\t}\n\n\tif (!user.name) {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/auth/startup.js#L187-L223","documentation":"Thrown by Rocket.Chat's user-creation flow: validateEmailDomain (called from onCreateUserAsync) fires when the setting Accounts_AllowedDomainsList is non-empty and the new user's first email address does not end with @<domain> for any domain in that comma-separated list. The regex is anchored at the end of the address, so subdomains and partial matches fail. It protects workspaces from registrations using email domains outside the approved set.","triggerScenarios":"Accounts.createUser (registration form), admin user creation, or SSO/auto-registration paths through Accounts.onCreateUser where user.emails[0].address does not match @domain$ for any entry of a non-blank Accounts_AllowedDomainsList.","commonSituations":"Admin restricts signups to corporate domains and a user registers with a public mailbox; a subdomain (mail.corp.com) is rejected because only corp.com is listed (anchored match); import/migration scripts creating users programmatically; stale whitelist entries after a company renames its domain.","solutions":["Add the exact email domain (the part after @, e.g. corp.com) to Accounts_AllowedDomainsList in Administration -> Accounts -> Registration","If the restriction is not intended, clear Accounts_AllowedDomainsList entirely (empty or blank disables the check)","Remember the match is suffix-anchored: list each subdomain explicitly (corp.com does not cover mail.corp.com)","For trusted programmatic creation (migrations/imports) pass options.skipEmailValidation = true so onCreateUserAsync skips validateEmailDomain"],"exampleFix":"// before\nawait createUserAccount({ email: 'dev@mail.corp.com', password, name });\n// throws error-invalid-domain when whitelist only contains corp.com\n\n// after\n// workspace setting Accounts_AllowedDomainsList: 'corp.com,mail.corp.com'\n// or, for a trusted server-side import:\nonCreateUserAsync.call(context, { skipEmailValidation: true, ...options }, userDoc);","handlingStrategy":"validation","validationCode":"const isEmailAllowed = (email: string, whitelistSetting: string | undefined): boolean => {\n  const list = String(whitelistSetting ?? '').split(',').map((d) => d.trim()).filter(Boolean);\n  if (list.length === 0) return true;\n  return list.some((domain) => email.trim().toLowerCase().endsWith('@' + domain.toLowerCase()));\n};\n\n// before Accounts.createUser / registration:\nif (!isEmailAllowed(email, settings.get('Accounts_AllowedDomainsList'))) {\n  throw new Error('Email domain not allowed for registration');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Accounts.createUserAsync(...);\n} catch (e) {\n  if (e instanceof Meteor.Error && e.error === 'error-invalid-domain') {\n    // permanent policy rejection: fix the whitelist or the email, never retry\n  }\n  throw e;\n}","preventionTips":["Keep Accounts_AllowedDomainsList as exact suffix domains; add every subdomain explicitly","Pass skipEmailValidation: true in trusted import/migration code","Show the allowed domains as a hint on the signup form so users self-correct"],"tags":["authentication","user-registration","email-validation","settings","whitelist"],"backgroundTag":"email-domain-not-allowed","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}