jeecgboot/JeecgBoot · error · JeecgBootException
用户尚有未退出的组织,无法删除!
Error message
用户尚有未退出的组织,无法删除!
What it means
deleteUserByPassword throws (step2 continued) when getTenantIdsByUserId returns a non-empty list — the user still belongs to other tenants/orgs. Full deletion would orphan their membership elsewhere, so it is blocked until all orgs are exited.
Source
Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantServiceImpl.java:912
//被删除人的用户id
String userId = sysUser.getId();
//被删除人的密码
String password = sysUser.getPassword();
//当前登录用户
LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
//step1 判断当前用户是否为当前租户的管理员(只有超级管理员和账号管理员可以删除)
Long isHaveAdmin = sysTenantPackUserMapper.izHaveBuyAuth(user.getId(), tenantId);
if(null == isHaveAdmin || 0 == isHaveAdmin){
throw new JeecgBootException("您不是当前组织的管理员,无法删除用户!");
}
//step2 离职状态下,并且无其他组织情况下,可以删除
SysUserTenant sysUserTenant = userTenantMapper.getUserTenantByTenantId(userId, tenantId);
if(null == sysUserTenant || !CommonConstant.USER_TENANT_QUIT.equals(sysUserTenant.getStatus())){
throw new JeecgBootException("用户没有离职,不允许删除!");
}
List<Integer> tenantIdsByUserId = userTenantMapper.getTenantIdsByUserId(userId);
if(CollectionUtils.isNotEmpty(tenantIdsByUserId) && tenantIdsByUserId.size()>0){
throw new JeecgBootException("用户尚有未退出的组织,无法删除!");
}
//step3 当天创建的用户和创建人可以删除
SysUser sysUserData = userService.getById(userId);
if(!sysUserData.getCreateBy().equals(user.getUsername())){
throw new JeecgBootException("您不是该用户的创建人,无法删除!");
}
// 代码逻辑说明: 【QQYUN-11839】删除用户,需要输入被删除用户的密码,这逻辑对吗?不应该是管理员的密码吗---
this.verifyCreateTimeAndPassword(sysUserData,password);
//step5 逻辑删除用户
userService.deleteUser(userId);
//step6 真实删除用户
userService.removeLogicDeleted(Collections.singletonList(userId));
}
/**
* 验证创建时间和密码View on GitHub (pinned to 96fb33f5ec)
Solutions
- Process the user's resignation from all other tenants first until getTenantIdsByUserId returns empty.
- Review the list of remaining tenants returned and exit each.
- If relations are stale, remove them administratively, then retry deletion.
- Frontend should show the remaining orgs so the operator knows what to clear.
Example fix
// before
tenantService.deleteUserByPassword(targetUser, tenantId);
// after
List<Integer> remaining = userTenantMapper.getTenantIdsByUserId(targetUser.getId());
if (CollectionUtils.isNotEmpty(remaining)) {
return Result.error("用户仍属于其它组织:" + remaining + ",请先全部退出");
}
tenantService.deleteUserByPassword(targetUser, tenantId); Defensive patterns
Strategy: validation
Validate before calling
List<Integer> remaining = userTenantMapper.getTenantIdsByUserId(userId);
if (CollectionUtils.isNotEmpty(remaining)) {
return Result.error("用户仍属于其它组织:" + remaining);
} Prevention
- Show remaining orgs to the operator before deletion.
- Exit all other tenants first.
- Clean up stale relations administratively.
When it happens
Trigger: The user has resigned from the current tenant but still has active relations in one or more other tenants. The deletion is refused to preserve referential integrity across organizations.
Common situations: Multi-tenant user who resigned from one org but remains in others; stale relations not cleaned up after prior exits; the operator overlooked other memberships.
Related errors
- 用户没有离职,不允许删除!
- 您不是当前组织的管理员,无法删除用户!
- 您不是该用户的创建人,无法删除!
- 用户不是今天创建的,无法删除!
- 当前部门类型为【${DepartCategoryEnum.getNameByValue(oldOrgCategory)}
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/8cdb6ec85149eb3c.
Report an issue: GitHub.