RocketChat/Rocket.Chat · error · Error

department-not-found

department-not-found

Error message

department-not-found

What it means

Thrown by `archiveDepartment(_id)` (departmentsLib.ts:157) when `LivechatDepartment.findOneById` with projection `{ _id, businessHourId }` returns null. Note it is a plain `new Error('department-not-found')`, not a `Meteor.Error`, so there is no structured code/metadata — callers must match on the message.

Source

Thrown at apps/meteor/server/lib/omnichannel/departmentsLib.ts:155

	if (department?.enabled && !departmentDB?.enabled) {
		await callbacks.run('livechat.afterDepartmentDisabled', departmentDB);
		void Apps.self?.triggerEvent(AppEvents.IPostLivechatDepartmentDisabled, { department: departmentDB });
	}

	if (departmentUnit) {
		await callbacks.run('livechat.manageDepartmentUnit', { userId, departmentId: departmentDB._id, unitId: departmentUnit._id });
	}

	return departmentDB;
}

export async function archiveDepartment(_id: string) {
	const department = await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id' | 'businessHourId'>>(_id, {
		projection: { _id: 1, businessHourId: 1 },
	});

	if (!department) {
		throw new Error('department-not-found');
	}

	const status = await LivechatDepartment.archiveDepartment(department._id);
	if (status.modifiedCount) {
		await afterDepartmentArchived(department);
	}
}

export async function unarchiveDepartment(_id: string) {
	const department = await LivechatDepartment.findOneById<Pick<ILivechatDepartment, '_id'>>(_id, { projection: { _id: 1 } });

	if (!department) {
		throw new Meteor.Error('department-not-found');
	}

	const status = await LivechatDepartment.unarchiveDepartment(department._id);
	if (status.modifiedCount) {
		await afterDepartmentUnarchived(department);

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Reload the department list and confirm the id still exists; if gone, the goal is already achieved — treat as success
  2. Guard with an existence check before calling archiveDepartment
  3. If wrapping this in an API, catch the plain Error and map 'department-not-found' to a 404-style response

Example fix

// before
await archiveDepartment(maybeStaleId);

// after
const dep = await LivechatDepartment.findOneById(maybeStaleId, { projection: { _id: 1 } });
if (!dep) return; // already gone — nothing to archive
await archiveDepartment(maybeStaleId);
Defensive patterns

Strategy: validation

Validate before calling

const dep = await LivechatDepartment.findOneById(_id, { projection: { _id: 1 } });
if (!dep) return; // nothing to archive — treat as done
await archiveDepartment(_id);

Type guard

const isExistingDepartment = async (id: string): Promise<boolean> =>
  (await LivechatDepartment.findOneById(id, { projections: { _id: 1 } } as any)) != null;

Try / catch

try {
  await archiveDepartment(_id);
} catch (e) {
  // plain Error here — match on message, not a Meteor.Error code
  if (e instanceof Error && e.message === 'department-not-found') {
    // idempotent: already deleted elsewhere
  }
}

Prevention

When it happens

Trigger: Archiving a department id that was already deleted (double action, stale table row), a typo'd id, or a REST/Meteor call racing another admin's delete.

Common situations: Two admins working the departments list; retry of an archive action after the first succeeded via a different path; frontend not refreshing after deletion.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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