nocobase/nocobase · error
Invalid main department, it must be one of the user's depart
Error message
Invalid main department, it must be one of the user's departments
What it means
The departments plugin registers a beforeSignIn handler that verifies a user's chosen main department (mainDepartmentId) actually belongs to the user's own department list; the users table may be edited directly or through non-UI flows, so this hook re-checks at sign-in load time. If the main department is not among the user's departments, it throws 'Invalid main department, it must be one of the user's departments' to keep user↔department consistency.
Source
Thrown at packages/plugins/@nocobase/plugin-departments/src/server/plugin.ts:142
userId: userId,
departmentId: mainDepartmentId,
},
transaction,
});
if (userDepartment) {
return;
}
}
if (Array.isArray(submittedDepartments)) {
const included = submittedDepartments.some((d) => {
const id = typeof d === 'object' ? d && (d.id ?? d) : d;
return `${id}` === `${mainDepartmentId}`;
});
if (included) {
return;
}
}
throw new Error(`Invalid main department, it must be one of the user's departments`);
});
this.app.on('beforeSignOut', ({ userId }) => {
this.app.cache.del(`departments:${userId}`);
});
const userDataSyncPlugin = this.app.pm.get('user-data-sync') as PluginUserDataSyncServer;
if (userDataSyncPlugin && userDataSyncPlugin.enabled) {
userDataSyncPlugin.resourceManager.registerResource(new DepartmentDataSyncResource(this.db, this.app.logger), {
// write department records after writing user records
after: 'users',
});
}
}
async install(options?: InstallOptions) {
const collectionRepo = this.db.getRepository<any>('collections');
if (collectionRepo) {View on GitHub (pinned to fa42722fef)
Solutions
- Update the user: set their main department to one they actually belong to (via the users/departments admin UI)
- Add the user back to the department referenced by mainDepartmentId, or clear mainDepartmentId (set to null) to fall back to the default
- Fix data directly: SELECT memberships for the user and align mainDepartmentId with one of them before retrying sign-in
- Audit import/sync scripts to always write memberships and mainDepartmentId atomically
Example fix
// before (stale data)
user.mainDepartmentId = 12; // user no longer member of dept 12
// after
db.getRepository('users').update({ id: user.id, mainDepartmentId: null }); // or set to a department the user belongs to Defensive patterns
Strategy: validation
Validate before calling
const memberships = await db.getRepository('departments_users').find({ filter: { userId } });
const deptIds = memberships.map((m) => String(m.departmentId));
if (user.mainDepartmentId && !deptIds.includes(String(user.mainDepartmentId))) {
await db.getRepository('users').update({
filterByTk: user.id,
values: { mainDepartmentId: deptIds[0] ?? null },
});
} Type guard
function hasValidMainDepartment(user: { mainDepartmentId: number | null; departments?: Array<{ id: number }> }): boolean {
return user.mainDepartmentId == null || !!user.departments?.some((d) => String(d.id) === String(user.mainDepartmentId));
} Try / catch
try {
await signIn(user);
} catch (err) {
if (/Invalid main department/.test(err.message)) {
await resetMainDepartment(user.id); // null it out or pick a real membership
await signIn(user);
} else {
throw err;
}
} Prevention
- Always clear/update mainDepartmentId when removing a user from a department
- Run a periodic integrity check joining users.mainDepartmentId against departments_users
- Make import/sync jobs set memberships and main department in one transaction
When it happens
Trigger: Signing in (beforeSignIn event) when the user record's mainDepartmentId references a department the user is not a member of — e.g. the user was removed from their main department without clearing mainDepartmentId, or mainDepartmentId was set to a department via direct DB/import updates.
Common situations: Admin removed the user from a department but the main-department pointer stayed; data import/sync wrote mainDepartmentId without memberships; a bug or manual DB edit left a stale id; deleting/reassigning departments out from under users.
Related errors
- APP_NOT_INSTALLED_ERROR
- invalid sessionId
- Conversation not existed
- Fail to create new agent thread
- AI employee model not configured
AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01).
Data as JSON: /api/errors/a5403c84d1b8cc25.
Report an issue: GitHub.