elunez/eladmin · warning · BadRequestException

A new menu cannot already have an ID

Error message

A new menu cannot already have an ID

What it means

Thrown by MenuController.createMenu (line 128) when the POST /api/menus body includes a non-null id. Menus are hierarchical entities whose ids are database-assigned; the guard enforces the create-before-identity contract and returns 400 before menuService.create runs, preventing accidental row shadowing.

Source

Thrown at eladmin-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java:128

                        menu.setSubCount(menu.getSubCount() - 1);
                    }
                }
                menuDtos.addAll(menuDtoList);
            }
            // 编辑菜单时不显示自己以及自己下级的数据,避免出现PID数据环形问题
            menuDtos = menuDtos.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
            return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK);
        }
        return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK);
    }

    @Log("新增菜单")
    @ApiOperation("新增菜单")
    @PostMapping
    @PreAuthorize("@el.check('menu:add')")
    public ResponseEntity<Object> createMenu(@Validated @RequestBody Menu resources){
        if (resources.getId() != null) {
            throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
        }
        menuService.create(resources);
        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    @Log("修改菜单")
    @ApiOperation("修改菜单")
    @PutMapping
    @PreAuthorize("@el.check('menu:edit')")
    public ResponseEntity<Object> updateMenu(@Validated(Menu.Update.class) @RequestBody Menu resources){
        menuService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @Log("删除菜单")
    @ApiOperation("删除菜单")
    @DeleteMapping
    @PreAuthorize("@el.check('menu:del')")

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Remove id from the payload before POST /api/menus; keep only pid and the fields you want.
  2. When duplicating a menu, map explicitly to a new object instead of POSTing the fetched entity.
  3. Reset the menu form (id = null, keep pid if creating a child) when the dialog opens in create mode.

Example fix

// before (duplicate a menu by posting the fetched row)
axios.post('/api/menus', this.selectedMenu)
// after
const { id, children, ...payload } = this.selectedMenu;
axios.post('/api/menus', payload)
Defensive patterns

Strategy: validation

Validate before calling

const { id, children, createTime, ...payload } = selectedMenu;
axios.post('/api/menus', payload); // duplication without id

Type guard

const isCreatePayload = (m) => m.id === undefined || m.id === null;

Prevention

When it happens

Trigger: Menu management tree dialog switching from edit to create without clearing the form; POSTing a Menu object fetched from GET /api/menus (e.g. to duplicate a menu); tooling that copies a whole menu subtree including ids.

Common situations: Front-end reuses the selected tree node (with id) as the base for a new sibling menu; menu duplication workflows; copying menu configuration between instances.

Related errors


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