RocketChat/Rocket.Chat · error · Error

error-custom-field-not-allowed

error-custom-field-not-allowed

Error message

error-custom-field-not-allowed

What it means

After validating known fields, validateCustomFields walks every key of the submitted customFields object and rejects any key not present in allowedCustomFields when ignoreAdditionalFields is false. This is a closed-world check: the payload may only contain fields that are defined (and passed in as allowed) — unknown properties are an error, not ignored.

Source

Thrown at apps/meteor/server/lib/omnichannel/contacts/validateCustomFields.ts:50

		if (cf.regexp) {
			const regex = new RegExp(cf.regexp);
			if (!regex.test(cfValue)) {
				if (ignoreValidationErrors) {
					continue;
				}

				throw new Error(i18n.t('error-invalid-custom-field-value', { field: cf.label || cf._id }));
			}
		}

		validValues[cf._id] = cfValue;
	}

	if (!ignoreAdditionalFields) {
		const allowedCustomFieldIds = new Set(allowedCustomFields.map((cf) => cf._id));
		for (const key in customFields) {
			if (!allowedCustomFieldIds.has(key)) {
				throw new Error(i18n.t('error-custom-field-not-allowed', { key }));
			}
		}
	}

	return validValues;
}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Remove keys that are not defined custom-field ids, or create the missing field in Administration > Omnichannel > Custom Fields
  2. Whitelist client-side: filter the payload to ids returned by GET /api/v1/livechat/custom-fields before submitting
  3. For tolerant ingestion paths, use a code path that passes ignoreAdditionalFields: true

Example fix

// before
customFields: { company: 'ACME', internal_note: 'x' } // 'internal_note' is not a defined field

// after
const defined = new Set((await LivechatCustomField.find().toArray()).map((f) => f._id));
customFields = Object.fromEntries(Object.entries(customFields).filter(([k]) => defined.has(k)));
Defensive patterns

Strategy: validation

Validate before calling

const allowed = new Set((await LivechatCustomField.find().toArray()).map((f) => f._id));
const filtered = Object.fromEntries(Object.entries(customFields).filter(([k]) => allowed.has(k)));
// pass `filtered` instead of the raw payload

Type guard

const containsOnlyAllowedKeys = (payload: Record<string, unknown>, allowed: Set<string>): boolean =>
  Object.keys(payload).every((k) => allowed.has(k));

Try / catch

try {
  await registerContact(params, userId);
} catch (err) {
  if (err instanceof Error && err.message.includes('error-custom-field-not-allowed')) {
    // message names the offending key: remove it or define the field, then retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Submitting customFields containing a key that is not a defined Livechat Custom Field id (typo, stale field, client-side bookkeeping property) through a code path that does not set ignoreAdditionalItems/ignoreAdditionalFields.

Common situations: A custom field was deleted server-side but old clients still send it; client injects metadata keys like '_updatedAt' or 'source' into the same object; copy-paste field id with different casing.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/4d6c940e77afa949. Report an issue: GitHub.