jeecgboot/JeecgBoot · error · JeecgBootException
离职失败,租户不存在
Error message
离职失败,租户不存在
What it means
Thrown by SysUserServiceImpl.userQuit when TenantContext.getTenant() resolves to 0 (default/empty). Quitting requires a tenant context because it updates sys_user_tenant status to USER_TENANT_QUIT for that tenant.
Source
Thrown at jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysUserServiceImpl.java:957
loginUser.setOrgId(this.getDepartIdByOrCode(sysUser.getOrgCode()));
// 查询当前登录用户的角色code(多个逗号分割)
loginUser.setRoleCode(this.getJoinRoleCodeByUserId(sysUser.getId()));
return loginUser;
}
@Override
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
@Transactional(rollbackFor = Exception.class)
public void userQuit(String username) {
SysUser sysUser = userMapper.getUserByName(username);
if(null == sysUser){
throw new JeecgBootException("离职失败,该用户已不存在");
}
// 代码逻辑说明: [QQYUN-3951]租户用户离职重构------------
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
//更新用户租户表的状态为离职状态
if(tenantId==0){
throw new JeecgBootException("离职失败,租户不存在");
}
LambdaQueryWrapper<SysUserTenant> query = new LambdaQueryWrapper<>();
query.eq(SysUserTenant::getUserId,sysUser.getId());
query.eq(SysUserTenant::getTenantId,tenantId);
SysUserTenant userTenant = new SysUserTenant();
userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
userTenantMapper.update(userTenant,query);
}
@Override
public List<SysUser> getQuitList(Integer tenantId) {
return userMapper.getTenantQuitList(tenantId);
}
@Override
public void updateStatusAndFlag(List<String> userIds, SysUser sysUser) {
userMapper.updateStatusAndFlag(userIds,sysUser);
}View on GitHub (pinned to 96fb33f5ec)
Solutions
- Ensure the tenant context header is set on the request before calling userQuit.
- Verify the tenant interceptor/filter populates TenantContext for this route.
- If the user truly has no tenant, quit is not the right operation - use account deletion instead.
- Confirm TenantContext.getTenant() returns the intended tenant id, not the default 0.
Example fix
// before: no tenant header userService.userQuit(username); // tenantId==0 -> throws // after: set tenant context (interceptor) or pass explicitly TenantContext.setTenant(String.valueOf(targetTenantId)); userService.userQuit(username);
Defensive patterns
Strategy: validation
Validate before calling
int tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
if (tenantId == 0) return Result.error("缺少租户上下文");
userService.userQuit(username); Type guard
boolean hasTenantContext() {
return oConvertUtils.getInt(TenantContext.getTenant(), 0) != 0;
} Try / catch
try { userService.userQuit(username); }
catch (JeecgBootException e) {
if (e.getMessage().contains("租户不存在")) return Result.error("请设置租户标识后重试");
throw e;
} Prevention
- Ensure the tenant interceptor sets TenantContext for quit routes.
- Send the X-Tenant-Id header from the client.
- Reject quit for genuinely non-tenant contexts.
When it happens
Trigger: userQuit invoked with no tenant in the request header/context (TenantContext.getTenant returns null or '0', oConvertUtils.getInt defaults to 0).
Common situations: The X-Tenant-Id header / tenant context was not set (e.g. admin backdoor without tenant header); the interceptor that sets TenantContext was bypassed; the user is genuinely non-tenant and quit is not supported; token filter dropped tenant info.
Related errors
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/768b1e7180ff8de6.
Report an issue: GitHub.