{"record":{"id":"db2327e6ae14b7e1","repo":"RocketChat/Rocket.Chat","slug":"users-are-missing-required-data","errorCode":null,"errorMessage":"Users are missing required data.","messagePattern":"Users are missing required data\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/services/import/service.ts","lineNumber":125,"sourceCode":"\t\t\tcase 'canceled':\n\t\t\t\tthrow new Error('The current import operation is already finished.');\n\t\t}\n\t}\n\n\tpublic async addUsers(users: Omit<IImportUser, '_id' | 'services' | 'customFields'>[]): Promise<void> {\n\t\tif (!users.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst operation = await Imports.findLastImport();\n\n\t\tthis.assertsValidStateForNewData(operation);\n\n\t\tconst defaultRoles = getNewUserRoles();\n\t\tconst userRoles = new Set<string>(defaultRoles);\n\t\tfor await (const user of users) {\n\t\t\tif (!user.emails?.some((value) => value) || !user.importIds?.some((value) => value)) {\n\t\t\t\tthrow new Error('Users are missing required data.');\n\t\t\t}\n\n\t\t\tif (user.roles?.length) {\n\t\t\t\tfor (const roleId of user.roles) {\n\t\t\t\t\tuserRoles.add(roleId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (userRoles.size > 0 && !(await validateRoleList([...userRoles]))) {\n\t\t\tthrow new Error('One or more of the users have been assigned invalid roles.');\n\t\t}\n\n\t\tawait ImportData.col.insertMany(\n\t\t\tusers.map((data) => ({\n\t\t\t\t_id: new ObjectId().toHexString(),\n\t\t\t\tdata: {\n\t\t\t\t\t...data,","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/services/import/service.ts#L107-L143","documentation":"Thrown by the import service's addUsers when a user record in the batch has no usable emails or importIds (every entry falsy/empty). Each imported user must carry at least one non-empty email and one non-empty importId so the importer can dedupe and map identities later. The check runs per record, so one bad user aborts the whole batch before insertion.","triggerScenarios":"addUsers([{ username: 'x' }]) with emails: [] or importIds missing; source-system exports where some users have no email address; CSV/JSON mappings that drop the importId column.","commonSituations":"Migrating from chat systems that allow email-less accounts; hand-built import files omitting external ids; upstream data quality issues where emails are empty strings.","solutions":["Ensure every user record has at least one non-empty email and one non-empty importId","Generate deterministic importIds from the source system's user ids when missing","Filter or fix records before calling addUsers instead of retrying the whole batch"],"exampleFix":"// before\nawait service.addUsers([{ username: 'x', emails: [], importIds: [] }]);\n\n// after\nconst valid = users.filter((u) => u.emails?.some(Boolean) && u.importIds?.some(Boolean));\nawait service.addUsers(valid);","handlingStrategy":"validation","validationCode":"const invalid = users.filter((u) => !u.emails?.some(Boolean) || !u.importIds?.some(Boolean));\nif (invalid.length) {\n  throw new Error(`${invalid.length} users lack emails/importIds`);\n}\nawait service.addUsers(users);","typeGuard":"function isImportableUser(u: { emails?: string[]; importIds?: string[] }): boolean {\n  return Boolean(u.emails?.some(Boolean) && u.importIds?.some(Boolean));\n}","tryCatchPattern":null,"preventionTips":["Validate source exports for email-less accounts before migrating","Always map the source system's user id into importIds"],"tags":["import","validation","user-migration","rocket-chat"],"backgroundTag":"missing-required-argument","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}