RocketChat/Rocket.Chat · error · Error
error-business-hour-name-already-in-use
Error message
error-business-hour-name-already-in-use
What it means
Thrown by CustomBusinessHour.saveBusinessHour in Custom.ts:44 when a different business hour already uses the requested name. It looks up by {name} and only allows reuse when the found _id equals the one being saved (i.e. renaming to your own name is fine). NOTE: plain `new Error('error-business-hour-name-already-in-use')` — no Meteor.Error, so the code lives only in the message string.
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 f9d3ec372b)
Solutions
- Choose a unique business-hour name.
- Pre-list business hours and validate the name client-side before save.
- Match by message string 'error-business-hour-name-already-in-use' in the catch (no code available).
Example fix
// before
await businessHour.saveBusinessHour(payload);
// after
const clash = await LivechatBusinessHours.findOne({ name: payload.name }, { projection: { _id: 1 } });
if (clash && clash._id !== payload._id) {
throw new Error('name taken');
}
await businessHour.saveBusinessHour(payload); Defensive patterns
Strategy: validation
Validate before calling
const clash = await LivechatBusinessHours.findOne({ name: payload.name }, { projection: { _id: 1 } });
if (clash && clash._id !== payload._id) throw new Error('name taken'); Type guard
const isNameUnique = async (name: string, selfId?: string) => {
const c = await LivechatBusinessHours.findOne({ name }, { projection: { _id: 1 } });
return !c || c._id === selfId;
}; Try / catch
try { await bh.saveBusinessHour(payload); }
catch (e) {
if (e instanceof Error && e.message === 'error-business-hour-name-already-in-use') { /* rename */ return; }
throw e;
} Prevention
- Validate the name is unique before save.
- Show existing business-hour names in the form for quick comparison.
When it happens
Trigger: Creating a business hour with a name already taken, or renaming an existing hour to another hour's name. The check ignores _id equality for new records (businessHour._id undefined/falsy).
Common situations: Default 'Business Hours' name reused; admin copy operation that does not rename; CI fixture collision.
Related errors
- error-duplicated-sla
- error-not-authorized
- SLA with id ${_id} not found
- room-still-open
- improper-room-state
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/9ec2190c05ba7268.
Report an issue: GitHub.