{"record":{"id":"f2f1f71125718f1d","repo":"theonedev/onedev","slug":"cannot-reset-two-factor-authentication-for-service","errorCode":null,"errorMessage":"Cannot reset two factor authentication for service or AI account","messagePattern":"Cannot reset two factor authentication for service or AI account","errorType":"http","errorClass":"ExplicitException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java","lineNumber":547,"sourceCode":"\t\t\tuserService.update(user, null);\n\t\t\treturn Response.ok().build();\n    \t} else {\n\t\t\tthrow new UnauthorizedException();\n\t\t}\n    }\n\n\t@Api(order=2025)\n\t@Path(\"/{userId}/two-factor-authentication\")\n\t@DELETE\n\tpublic Response resetTwoFactorAuthentication(@PathParam(\"userId\") Long userId) {\n\t\tif (!SecurityUtils.isAdministrator()) \n\t\t\tthrow new UnauthorizedException();\n\n\t\tUser user = userService.load(userId);\t\t\n\t\tif (user.isDisabled()) {\n\t\t\tthrow new ExplicitException(\"Cannot reset two factor authentication for disabled account\");\n\t\t} else if (user.getType() != ORDINARY) {\n\t\t\tthrow new ExplicitException(\"Cannot reset two factor authentication for service or AI account\");\n\t\t} else {\n\t\t\tuser.setTwoFactorAuthentication(null);\n\t\t\tuserService.update(user, null);\n\t\t\tauditService.audit(null, \"reset two factor authentication of account \\\"\" + user.getName() + \"\\\" via RESTful API\", null, null);\n\t\t\treturn Response.ok().build();\n\t\t}\n\t}\n\t\n\t@Api(order=2100)\n\t@Path(\"/{userId}/queries-and-watches\")\n    @POST\n    public Response setQueriesAndWatches(@PathParam(\"userId\") Long userId, @NotNull QueriesAndWatches queriesAndWatches) {\n    \tUser user = userService.load(userId);\n    \tif (!SecurityUtils.isAdministrator() && !user.equals(getAuthUser())) \n\t\t\tthrow new UnauthorizedException();\n\n\t\tif (user.isDisabled()) \n\t\t\tthrow new ExplicitException(\"Cannot set queries and watches for disabled user\");","sourceCodeStart":529,"sourceCodeEnd":565,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java#L529-L565","documentation":"Two-factor authentication only exists for ordinary interactive-login users. If the target user's type is not ORDINARY (service or AI account), the resetTwoFactorAuthentication endpoint rejects the request. Service and AI accounts never enroll in 2FA, so there is nothing to reset.","triggerScenarios":"Calling POST /rest/v1/users/{userId}/reset-two-factor-authentication for a service or AI account instead of an ordinary user.","commonSituations":"Bulk security scripts resetting 2FA for every account; confusing a service account id with a user's id; applying incident-response 2FA resets to bot accounts.","solutions":["Verify the target user's type is ORDINARY before resetting 2FA","Exclude service and AI accounts from bulk 2FA reset operations","Check the account type via GET /users/{userId} first"],"exampleFix":"// before\nawait rest.post(`/users/${svc.id}/reset-two-factor-authentication`); // 400: not ORDINARY\n// after\nconst user = await rest.get(`/users/${svc.id}`);\nif (user.type === 'ORDINARY') {\n  await rest.post(`/users/${svc.id}/reset-two-factor-authentication`);\n}","handlingStrategy":"validation","validationCode":"const user = await rest.get(`/users/${userId}`); if (user.type !== 'ORDINARY') throw new Error('2FA can only be reset for ordinary users');","typeGuard":"function isOrdinaryUser(user) { return user.type === 'ORDINARY'; }","tryCatchPattern":"try { await rest.post(`/users/${id}/reset-two-factor-authentication`); } catch (e) { if (e.status === 400 && /service or AI account/.test(e.message)) { /* skip non-interactive accounts */ } else throw e; }","preventionTips":["Restrict 2FA reset scripts to ORDINARY accounts","Remember service/AI accounts never enroll in 2FA","Fetch account type before security operations"],"tags":["rest-api","two-factor-authentication","account-type","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-14T00:17:10.932Z"}