elunez/eladmin · error · BadRequestException

上级不能为自己

Error message

上级不能为自己

What it means

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.

Source

Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java:150

            resources.setPid(null);
        }
        if(resources.getIFrame()){
            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {
                throw new BadRequestException(BAD_REQUEST);
            }
        }
        menuRepository.save(resources);
        // 计算子节点数目
        resources.setSubCount(0);
        // 更新父节点菜单数目
        updateSubCnt(resources.getPid());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Menu resources) {
        if(resources.getId().equals(resources.getPid())) {
            throw new BadRequestException("上级不能为自己");
        }
        Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new);
        ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId());

        if(resources.getIFrame()){
            if (!(resources.getPath().toLowerCase().startsWith(HTTP_PRE)||resources.getPath().toLowerCase().startsWith(HTTPS_PRE))) {
                throw new BadRequestException(BAD_REQUEST);
            }
        }
        Menu menu1 = menuRepository.findByTitle(resources.getTitle());

        if(menu1 != null && !menu1.getId().equals(menu.getId())){
            throw new EntityExistException(Menu.class,"title",resources.getTitle());
        }

        if(resources.getPid().equals(0L)){
            resources.setPid(null);
        }

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Pick a different parent (or clear pid to null/0 for a root menu) before saving.
  2. Fix the front-end parent selector to filter out the current menu node from the candidate parent tree.
  3. Validate id !== pid client-side before issuing the PUT.

Example fix

// before
menu.setPid(menu.getId()); // self-parent rejected

// after: root-level menu
menu.setPid(null); // or 0L, which the service converts to null
Defensive patterns

Strategy: validation

Validate before calling

if (Objects.equals(form.id, form.pid)) { alert('上级菜单不能为自身'); return; }

Type guard

const isValidParent = (id: number, pid: number | null) => pid === null || pid !== id;

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/728538281a7360a2. Report an issue: GitHub.