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

  1. Update the user: set their main department to one they actually belong to (via the users/departments admin UI)
  2. Add the user back to the department referenced by mainDepartmentId, or clear mainDepartmentId (set to null) to fall back to the default
  3. Fix data directly: SELECT memberships for the user and align mainDepartmentId with one of them before retrying sign-in
  4. 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

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


AI-assisted analysis of nocobase/nocobase@fa42722fef (2026-09-01). Data as JSON: /api/errors/a5403c84d1b8cc25. Report an issue: GitHub.