RocketChat/Rocket.Chat · error · Error

error-business-hour-name-already-in-use

Error message

error-business-hour-name-already-in-use

What it means

saveBusinessHour in the Custom (single/timezone) business-hour implementation queries for an existing business hour with the same name. If one exists with a different _id, it throws error-business-hour-name-already-in-use to keep names unique.

Solutions

  1. Choose a distinct name for the business hour
  2. Rename or delete the existing business hour that holds the name first
  3. When duplicating for another timezone, append the timezone to the name
Defensive patterns

Strategy: validation

Validate before calling

const existing = await LivechatBusinessHours.findOneByName(businessHour.name);
if (existing && existing._id !== businessHour._id) {
	// name taken: ask for a different name before saving
}
await saveBusinessHour(businessHour);

Try / catch

try {
	await saveBusinessHour(businessHour);
} catch (err) {
	if (err instanceof Error && err.message === 'error-business-hour-name-already-in-use') {
		// prompt for a unique name; keep form data intact
	} else {
		throw err;
	}
}

Prevention

When it happens

Trigger: Creating a business hour whose name is already taken, or renaming a business hour to another one's name (existingBusinessHour._id !== businessHour._id).

Common situations: Admins creating similarly named business hours ('Business Hours' vs 'business hours'); importing a duplicate configuration; copy-then-rename workflows that keep the original name.

Related errors


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

Appendix: source

Thrown at apps/meteor/ee/server/lib/omnichannel/business-hour/Custom.ts:44

		const businessHour = await this.BusinessHourRepository.findOneById(id);
		if (!businessHour) {
			return null;
		}

		businessHour.departments = await LivechatDepartment.findByBusinessHourId(businessHour._id, {
			projection: { name: 1 },
		}).toArray();
		return businessHour;
	}

	async saveBusinessHour(businessHour: ILivechatBusinessHour & IBusinessHoursExtraProperties): Promise<ILivechatBusinessHour> {
		const existingBusinessHour = (await this.BusinessHourRepository.findOne(
			{ name: businessHour.name },
			{ projection: { _id: 1 } },
		)) as ILivechatBusinessHour;
		if (existingBusinessHour && existingBusinessHour._id !== businessHour._id) {
			throw new Error('error-business-hour-name-already-in-use');
		}
		const { timezoneName, departmentsToApplyBusinessHour, ...businessHourData } = businessHour;
		businessHourData.timezone = {
			name: timezoneName,
			utc: this.getUTCFromTimezone(timezoneName),
		};
		const businessHourToReturn = { ...businessHourData, departmentsToApplyBusinessHour };
		delete businessHourData.departments;

		const businessHourId = await this.baseSaveBusinessHour(businessHourData);

		// Internal callers (e.g. the DST verifier) re-save business hours without the
		// departments field; only reconcile department links when it is provided,
		// otherwise an internal re-save would unlink every department.
		if (departmentsToApplyBusinessHour !== undefined) {
			const departments = departmentsToApplyBusinessHour.split(',').filter(Boolean);
			const currentDepartments = (
				await LivechatDepartment.findByBusinessHourId(businessHourId, {

View on GitHub (pinned to b2c16d5842)