{"record":{"id":"728538281a7360a2","repo":"elunez/eladmin","slug":"error-728538","errorCode":null,"errorMessage":"上级不能为自己","messagePattern":"上级不能为自己","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java","lineNumber":150,"sourceCode":"            resources.setPid(null);\n        }\n        if(resources.getIFrame()){\n            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {\n                throw new BadRequestException(BAD_REQUEST);\n            }\n        }\n        menuRepository.save(resources);\n        // 计算子节点数目\n        resources.setSubCount(0);\n        // 更新父节点菜单数目\n        updateSubCnt(resources.getPid());\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public void update(Menu resources) {\n        if(resources.getId().equals(resources.getPid())) {\n            throw new BadRequestException(\"上级不能为自己\");\n        }\n        Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new);\n        ValidationUtil.isNull(menu.getId(),\"Permission\",\"id\",resources.getId());\n\n        if(resources.getIFrame()){\n            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {\n                throw new BadRequestException(BAD_REQUEST);\n            }\n        }\n        Menu menu1 = menuRepository.findByTitle(resources.getTitle());\n\n        if(menu1 != null && !menu1.getId().equals(menu.getId())){\n            throw new EntityExistException(Menu.class,\"title\",resources.getTitle());\n        }\n\n        if(resources.getPid().equals(0L)){\n            resources.setPid(null);\n        }","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/elunez/eladmin/blob/55fbf705956949697dbd68bf9003776609d3d029/eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java#L132-L168","documentation":"BadRequestException thrown in MenuServiceImpl.update when a menu's pid (parent id) equals its own id. Setting a menu as its own parent would create a self-referencing cycle in the menu tree, breaking tree building, lazy loading, and subCount maintenance.","triggerScenarios":"PUT /api/menus where the request body's id and pid are the same value (e.g. dragging a menu node onto itself in the tree editor, or a form that defaults pid to the menu's own id).","commonSituations":"Front-end tree selector not excluding the node being edited; importing edited menu JSON where pid was copied from id; drag-and-drop tree plugins firing a drop event on the same node.","solutions":["Pick a different parent (or clear pid to null/0 for a root menu) before saving.","Fix the front-end parent selector to filter out the current menu node from the candidate parent tree.","Validate id !== pid client-side before issuing the PUT."],"exampleFix":"// before\nmenu.setPid(menu.getId()); // self-parent rejected\n\n// after: root-level menu\nmenu.setPid(null); // or 0L, which the service converts to null","handlingStrategy":"validation","validationCode":"if (Objects.equals(form.id, form.pid)) { alert('上级菜单不能为自身'); return; }","typeGuard":"const isValidParent = (id: number, pid: number | null) => pid === null || pid !== id;","tryCatchPattern":null,"preventionTips":["Exclude the editing node from the parent tree selector","Clear pid to 0/null when making the menu a root","Validate id !== pid in the form schema before submit"],"tags":["eladmin","menu","tree","cycle","bad-request"],"backgroundTag":null,"analyzedSha":"55fbf705956949697dbd68bf9003776609d3d029","analyzedAt":"2026-08-14T11:56:12.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}