{"record":{"id":"7ee4fe7705c96467","repo":"elunez/eladmin","slug":"a-new-role-cannot-already-have-an-id","errorCode":null,"errorMessage":"A new role cannot already have an ID","messagePattern":"A new role cannot already have an ID","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java","lineNumber":98,"sourceCode":"    @GetMapping\n    @PreAuthorize(\"@el.check('roles:list')\")\n    public ResponseEntity<PageResult<RoleDto>> queryRole(RoleQueryCriteria criteria, Pageable pageable){\n        return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK);\n    }\n\n    @ApiOperation(\"获取用户级别\")\n    @GetMapping(value = \"/level\")\n    public ResponseEntity<Object> getRoleLevel(){\n        return new ResponseEntity<>(Dict.create().set(\"level\", getLevels()),HttpStatus.OK);\n    }\n\n    @Log(\"新增角色\")\n    @ApiOperation(\"新增角色\")\n    @PostMapping\n    @PreAuthorize(\"@el.check('roles:add')\")\n    public ResponseEntity<Object> createRole(@Validated @RequestBody Role resources){\n        if (resources.getId() != null) {\n            throw new BadRequestException(\"A new \"+ ENTITY_NAME +\" cannot already have an ID\");\n        }\n        checkLevel(resources.getLevel());\n        roleService.create(resources);\n        return new ResponseEntity<>(HttpStatus.CREATED);\n    }\n\n    @Log(\"修改角色\")\n    @ApiOperation(\"修改角色\")\n    @PutMapping\n    @PreAuthorize(\"@el.check('roles:edit')\")\n    public ResponseEntity<Object> updateRole(@Validated(Role.Update.class) @RequestBody Role resources){\n        RoleDto role = roleService.findById(resources.getId());\n        checkLevel(role.getLevel());\n        checkLevel(resources.getLevel());\n        roleService.update(resources);\n        return new ResponseEntity<>(HttpStatus.NO_CONTENT);\n    }\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/elunez/eladmin/blob/55fbf705956949697dbd68bf9003776609d3d029/eladmin-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java#L80-L116","documentation":"Thrown by RoleController.createRole (line 98) when POST /api/roles carries a non-null id. Roles follow the same eladmin create contract; additionally this controller orders the guard before checkLevel and roleService.create, so an id-bearing body fails with 400 regardless of the level field.","triggerScenarios":"Role dialog left populated after an edit and reused for create; POSTing a RoleDto from GET /api/roles to clone a role's permission set; importing roles from another deployment with ids intact.","commonSituations":"'Copy role' workflows where the client posts the fetched role verbatim; shared add/edit dialog without form reset; environment sync scripts.","solutions":["Strip id (and menus if cloning is undesired) before POST /api/roles.","For role cloning, build a fresh payload: { name, level, dataScope, menus } without id.","Reset the role form whenever opening it in create mode."],"exampleFix":"// before (clone a role)\naxios.post('/api/roles', this.roleRow)\n// after\nconst { id, ...payload } = this.roleRow;\naxios.post('/api/roles', payload)","handlingStrategy":"validation","validationCode":"const { id, ...payload } = roleRow; // clone without identity\naxios.post('/api/roles', payload);","typeGuard":"const isCreateSafe = (r) => r.id == null;","tryCatchPattern":null,"preventionTips":["Separate 'clone role' logic from raw entity POST.","Reset role dialog state; include level explicitly so checkLevel does not hit the null branch."],"tags":["rest-api","validation","eladmin","role","crud"],"backgroundTag":null,"analyzedSha":"55fbf705956949697dbd68bf9003776609d3d029","analyzedAt":"2026-08-14T11:56:12.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}