jeecgboot/JeecgBoot · error · JeecgBootException

该用户还存在于其它组织中,无法删除用户!

Error message

该用户还存在于其它组织中,无法删除用户!

What it means

Thrown by SysTenantServiceImpl.deleteUser at step2. It queries sys_user_tenant for rows with the same userId but a different tenantId; if any exist it refuses the hard delete because the user still belongs to at least one other organization.

Source

Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java:980

    public void deleteUser(SysUser sysUser, Integer tenantId) {
        //被删除人的用户id
        String userId = sysUser.getId();
        //被删除人的密码
        String password = sysUser.getPassword();
        //当前登录用户
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        //step1 判断当前用户是否为当前租户的创建者才可以删除
        SysTenant sysTenant = this.getById(tenantId);
        if(null == sysTenant || !user.getUsername().equals(sysTenant.getCreateBy())){
            throw new JeecgBootException("您不是当前组织的创建者,无法删除用户!");
        }
        //step2 判断除了当前组织之外是否还有加入了其他组织
        LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
        query.eq(SysUserTenant::getUserId,userId);
        query.ne(SysUserTenant::getTenantId,tenantId);
        List<SysUserTenant> sysUserTenants = userTenantMapper.selectList(query);
        if(CollectionUtils.isNotEmpty(sysUserTenants)){
            throw new JeecgBootException("该用户还存在于其它组织中,无法删除用户!");
        }
        //step3 验证创建时间和密码
        SysUser sysUserData = userService.getById(userId);
        this.verifyCreateTimeAndPassword(sysUserData,password);
        //step4 真实删除用户
        userService.deleteUser(userId);
        userService.removeLogicDeleted(Collections.singletonList(userId));
    }

    /**
     * 为用户添加租户下所有套餐
     *
     * @param userId   用户id
     * @param tenantId 租户id
     */
    public void addPackUser(String userId, String tenantId) {
        //根据租户id和产品包的code获取租户套餐id
        List<String> packIds = sysTenantPackMapper.getPackIdByPackCodeAndTenantId(oConvertUtils.getInt(tenantId));

View on GitHub (pinned to 96fb33f5ec)

Solutions

  1. Remove the user from all other organizations first (delete sys_user_tenant rows for other tenantIds), then retry full deletion.
  2. Or call the org-removal endpoint instead of the full-delete endpoint when the user is multi-tenant.
  3. Audit sys_user_tenant for stray rows for this userId and clean them.
  4. Confirm whether the intended action is 'leave this org' vs 'permanently delete account'.

Example fix

// before: full delete while user is in other tenants
deleteUser(sysUser, tenantId);  // throws

// after: remove membership from each tenant, then delete
for (Integer tId : otherTenantIds) {
    userTenantMapper.delete(new LambdaQueryWrapper<SysUserTenant>()
        .eq(SysUserTenant::getUserId, userId).eq(SysUserTenant::getTenantId, tId));
}
deleteUser(sysUser, tenantId);
Defensive patterns

Strategy: validation

Validate before calling

LambdaQueryWrapper<SysUserTenant> q = new LambdaQueryWrapper<>();
q.eq(SysUserTenant::getUserId, userId).ne(SysUserTenant::getTenantId, tenantId);
if (userTenantMapper.selectList(q).size() > 0) {
    return Result.error("请先将用户移出其它组织");
}

Type guard

boolean isOnlyInThisTenant(String userId, Integer tenantId) {
  LambdaQueryWrapper<SysUserTenant> q = new LambdaQueryWrapper<>();
  q.eq(SysUserTenant::getUserId, userId).ne(SysUserTenant::getTenantId, tenantId);
  return userTenantMapper.selectCount(q) == 0;
}

Try / catch

try { sysTenantService.deleteUser(sysUser, tenantId); }
catch (JeecgBootException e) {
  if (e.getMessage().contains("其它组织")) { return Result.error(e.getMessage()); }
  throw e;
}

Prevention

When it happens

Trigger: A user who is a member of multiple tenants/organizations attempts full deletion while still linked to another tenant. The query uses userId and ne tenantId.

Common situations: User accepted invitations to several orgs; old tenant memberships were never removed; soft-deleted memberships still present as rows; the UI only removes from the current org but calls the full-delete API.

Related errors


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/9912908edcb0baa5. Report an issue: GitHub.