elunez/eladmin · error · BadRequestException
上级不能为自己
Error message
上级不能为自己
What it means
Thrown by DeptServiceImpl.update (line 130) on PUT /api/dept when the submitted pid equals the dept's own id — making the department its own parent. eladmin validates direct self-parenting before saving; deeper cycles (A→B→A) are NOT caught here and only surface later as broken tree queries.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java:130
@Transactional(rollbackFor = Exception.class)
public void create(Dept resources) {
deptRepository.save(resources);
// 计算子节点数目
resources.setSubCount(0);
// 清理缓存
updateSubCnt(resources.getPid());
// 清理自定义角色权限的datascope缓存
delCaches(resources.getPid());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(Dept resources) {
// 旧的部门
Long oldPid = findById(resources.getId()).getPid();
Long newPid = resources.getPid();
if(resources.getPid() != null && resources.getId().equals(resources.getPid())) {
throw new BadRequestException("上级不能为自己");
}
Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new);
ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId());
resources.setId(dept.getId());
deptRepository.save(resources);
// 更新父节点中子节点数目
updateSubCnt(oldPid);
updateSubCnt(newPid);
// 清理缓存
delCaches(resources.getId());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Set<DeptDto> deptDtos) {
for (DeptDto deptDto : deptDtos) {
// 清理缓存
delCaches(deptDto.getId());View on GitHub (pinned to 55fbf70595)
Solutions
- Pick a different parent (or null for a root dept) and resubmit.
- Front end: filter the current node (and ideally its subtree) out of the parent options: options.filter(node => node.id !== form.id).
- If importing data, pre-validate pid != id and no ancestor loops before calling the API.
Example fix
// before <el-cascader :options="deptTree" v-model="form.pid" /> // includes self // after <el-cascader :options="deptTree.filter(d => d.id !== form.id)" v-model="form.pid" />
Defensive patterns
Strategy: validation
Validate before calling
if (form.pid != null && form.pid === form.id) {
notifyError('上级不能为自己');
return;
}
await axios.put('/api/dept', form); Type guard
const pidIsValid = (form) => form.pid == null || form.pid !== form.id;
Prevention
- Exclude the edited node from the parent tree-select options.
- When importing dept data, validate pid != id (and no ancestor cycles) beforehand — the server only catches direct self-parenting.
When it happens
Trigger: Editing a dept and selecting itself in the parent-dept tree picker; front-end defaulting the pid selector to the node being edited; migrating dept data where source ids and parent ids collide.
Common situations: Tree-select component not excluding the current node from selectable parents; admin drags a dept onto itself in a tree editor; hand-written SQL updates setting pid = id by accident.
Related errors
- A new dept cannot already have an ID
- 文件超出规定大小:{maxSize}MB
- {entity} 不存在: {parameter} is {value}
- 没有这个选项
- 非法的应用名称,请勿包含[; | &]等特殊字符
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/0242b1486e1fb0ed.
Report an issue: GitHub.