{"record":{"id":"42893f2735c5d56e","repo":"RocketChat/Rocket.Chat","slug":"missing-required-custom-fields-errors-join","errorCode":null,"errorMessage":"Missing required custom fields: ${errors.join(', ')}","messagePattern":"Missing required custom fields: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/custom-fields.ts","lineNumber":18,"sourceCode":"import type { ILivechatContact, ILivechatCustomField, ILivechatVisitor } from '@rocket.chat/core-typings';\nimport { LivechatContacts, LivechatCustomField, LivechatRooms, LivechatVisitors } from '@rocket.chat/models';\n\nimport { livechatLogger } from './logger';\nimport { i18n } from '../../../app/utils/lib/i18n';\n\nexport const validateRequiredCustomFields = (customFields: string[], livechatCustomFields: ILivechatCustomField[]) => {\n\tconst errors: string[] = [];\n\tconst requiredCustomFields = livechatCustomFields.filter((field) => field.required);\n\n\trequiredCustomFields.forEach((field) => {\n\t\tif (!customFields.find((f) => f === field._id)) {\n\t\t\terrors.push(field._id);\n\t\t}\n\t});\n\n\tif (errors.length > 0) {\n\t\tthrow new Error(`Missing required custom fields: ${errors.join(', ')}`);\n\t}\n};\n\nexport async function updateContactsCustomFields(\n\tcontact: ILivechatContact,\n\tvalidCustomFields: {\n\t\tkey: string;\n\t\tvalue: string;\n\t\toverwrite: boolean;\n\t}[],\n): Promise<void> {\n\tconst contactCustomFieldsToUpdate = validCustomFields.reduce(\n\t\t(prev, curr) => {\n\t\t\tif (curr.overwrite || !contact?.customFields?.[curr.key]) {\n\t\t\t\tprev[`customFields.${curr.key}`] = curr.value;\n\t\t\t\treturn prev;\n\t\t\t}\n\t\t\tprev.conflictingFields ??= contact.conflictingFields || [];","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/custom-fields.ts#L1-L36","documentation":"validateRequiredCustomFields (used by setMultipleVisitorCustomFields before writing visitor/room custom fields) compares the list of field keys you are about to set against every field marked required in the definition. If any required field id is absent from your keys array, it throws a plain Error listing the missing ids in the message — note it has no error code, only the interpolated text.","triggerScenarios":"Calling setMultipleVisitorCustomFields (visitor registration/custom-field batch flows) with a keys list that covers only some fields, while at least one field in LivechatCustomField has required=true.","commonSituations":"New required field added by admins after the integration was written; webhook sends a dynamic subset of fields; required field hidden in the chat widget form.","solutions":["Include every required field id in the customFields array — the error message names exactly which ids are missing","Make the field optional in Administration > Omnichannel > Custom Fields if it should not block writes","Fetch required ids at runtime (GET /api/v1/livechat/custom-fields, filter required) instead of hardcoding the list"],"exampleFix":"// before\nawait setMultipleVisitorCustomFields({ token, customFields: [{ key: 'company', value: 'ACME', overwrite: true }] }); // 'address' required\n\n// after\nawait setMultipleVisitorCustomFields({ token, customFields: [\n  { key: 'company', value: 'ACME', overwrite: true },\n  { key: 'address', value: '1 Main St', overwrite: true },\n] });","handlingStrategy":"validation","validationCode":"const allFields = await LivechatCustomField.find().toArray();\nconst requiredIds = allFields.filter((f) => f.required).map((f) => f._id);\nconst missing = requiredIds.filter((id) => !keys.includes(id));\nif (missing.length) throw new Error(`Missing required custom fields: ${missing.join(', ')}`);\nawait setMultipleVisitorCustomFields(params);","typeGuard":"const coversRequired = (keys: string[], required: string[]): boolean =>\n  required.every((id) => keys.includes(id));","tryCatchPattern":"try {\n  await setMultipleVisitorCustomFields(params);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Missing required custom fields')) {\n    // parse field ids from the message, add them with valid values, retry\n  }\n  throw err;\n}","preventionTips":["Derive the key list from required-field metadata at runtime","Make fields optional when they should never block a visitor write","Test integrations after admins add new required fields"],"tags":["omnichannel","livechat","custom-fields","required-field","visitor","validation"],"backgroundTag":"required-field-missing","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}