{"record":{"id":"c33e348a33bf3189","repo":"theonedev/onedev","slug":"should-only-convert-normal-users-to-service-accoun","errorCode":null,"errorMessage":"Should only convert normal users to service accounts","messagePattern":"Should only convert normal users to service accounts","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java","lineNumber":474,"sourceCode":"\t\t\tthrow new BadRequestException(\"Should only enable normal users\");\n\t\tvar user = userService.load(userId);\n\t\tuserService.enable(user);\n\n\t\tauditService.audit(null, \"enabled account \\\"\" + user.getName() + \"\\\" via RESTful API\", null, null);\n\n\t\treturn Response.ok().build();\n    }\n\n\t@Api(order=1980, description=\"Convert to service account\")\n\t@Path(\"/{userId}/convert-to-service-account\")\n    @POST\n    public Response convertToServiceAccount(@PathParam(\"userId\") Long userId) {\n\t\tif (!subscriptionService.isSubscriptionActive())\n\t\t\tthrow new NotAcceptableException(\"This operation requires active subscription\");\n\t\tif (!SecurityUtils.isAdministrator()) \n\t\t\tthrow new UnauthorizedException();\n\t\tif (userId <= User.ROOT_ID)\t\t\n\t\t\tthrow new BadRequestException(\"Should only convert normal users to service accounts\");\n\t\tvar user = userService.load(userId);\n\t\tuserService.convertToServiceAccount(user);\n\n\t\tauditService.audit(null, \"converted user \\\"\" + user.getName() + \"\\\" to service account via RESTful API\", null, null);\n\n\t\treturn Response.ok().build();\n    }\n\t\n\t@Api(order=2000)\n\t@Path(\"/{userId}/password\")\n    @POST\n    public Response setPassword(@PathParam(\"userId\") Long userId, @Password(checkPolicy=true) @NotEmpty String password) {\n    \tUser user = userService.load(userId);\n\t\tif (user.isDisabled()) {\n\t\t\tthrow new ExplicitException(\"Cannot set password for disabled account\");\n\t\t} else if (user.getType() != ORDINARY) {\n\t\t\tthrow new ExplicitException(\"Cannot set password for service or AI account\");\n\t\t} if (SecurityUtils.isAdministrator()) {","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java#L456-L492","documentation":"The convert-to-service-account endpoint only accepts normal (ordinary) user ids. If userId <= User.ROOT_ID — i.e. a reserved/system account such as root — the request is rejected with this BadRequestException. Service accounts and the root account cannot be converted to service accounts again via the API.","triggerScenarios":"Calling POST /rest/v1/users/{userId}/convert-to-service-account with a userId that is the built-in root account or any reserved id <= User.ROOT_ID.","commonSituations":"Bulk scripts iterating all users including root; assuming ids start at 1/0 for real users; passing a wrong variable as userId.","solutions":["Check userId > User.ROOT_ID (and that the user type is ORDINARY) before calling the endpoint","Fetch the user list and skip system accounts (root) when scripting conversions","Convert privileged/system accounts manually if ever needed, not through this endpoint"],"exampleFix":"// before\nawait rest.post(`/users/${user.id}/convert-to-service-account`); // root id -> 400\n// after\nif (user.id > 1 && user.type === 'ORDINARY') {\n  await rest.post(`/users/${user.id}/convert-to-service-account`);\n}","handlingStrategy":"validation","validationCode":"if (typeof userId !== 'number' || userId <= 1) throw new Error('Only normal users (id > User.ROOT_ID) can be converted to service accounts');","typeGuard":"function isConvertibleUser(user) { return user.id > 1 && user.type === 'ORDINARY'; }","tryCatchPattern":"try { await rest.post(`/users/${id}/convert-to-service-account`); } catch (e) { if (e.status === 400 && /normal users/.test(e.message)) { /* skip reserved account */ } else throw e; }","preventionTips":["Exclude reserved/system accounts (root) from conversion scripts","Convert only accounts whose type is ORDINARY","Fetch account metadata before mutating it via REST"],"tags":["rest-api","user-management","bad-request","onedev"],"backgroundTag":"invalid-argument-value","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}