{"record":{"id":"7c00048a0f4ce685","repo":"theonedev/onedev","slug":"cannot-set-queries-and-watches-for-disabled-user","errorCode":null,"errorMessage":"Cannot set queries and watches for disabled user","messagePattern":"Cannot set queries and watches for disabled user","errorType":"http","errorClass":"ExplicitException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java","lineNumber":565,"sourceCode":"\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\");\n\t\telse if (user.getType() != ORDINARY) \n\t\t\tthrow new ExplicitException(\"Cannot set queries and watches for service or ai account\");\n\n\t\tvar oldAuditContent = VersionedXmlDoc.fromBean(getQueriesAndWatches(user)).toXML();\n\n\t\tuser.setBuildQuerySubscriptions(queriesAndWatches.buildQuerySubscriptions);\n\t\tuser.setIssueQueryWatches(queriesAndWatches.issueQueryWatches);\n\t\tuser.setPullRequestQueryWatches(queriesAndWatches.pullRequestQueryWatches);\n\t\tuser.setBuildQueries(queriesAndWatches.buildQueries);\n\t\tuser.setIssueQueries(queriesAndWatches.issueQueries);\n\t\tuser.setProjectQueries(queriesAndWatches.projectQueries);\n\t\tuser.setPullRequestQueries(queriesAndWatches.pullRequestQueries);\n\t\tuser.setPackQueries(queriesAndWatches.packQueries);\n\t\tuser.setPackQuerySubscriptions(queriesAndWatches.packQuerySubscriptions);\n\t\tuser.setWorkspaceQueries(queriesAndWatches.workspaceQueries);\n\t\tuser.setWorkspaceQuerySubscriptions(queriesAndWatches.workspaceQuerySubscriptions);\n\t\tuserService.update(user, null);\n","sourceCodeStart":547,"sourceCodeEnd":583,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java#L547-L583","documentation":"OneDev throws this ExplicitException from the REST endpoint PUT /users/{userId}/queries-and-watches when the target user account is disabled. The API refuses to update build/issue/PR query subscriptions and watches for accounts that can no longer log in, since watch settings are meaningless for inactive accounts. Only administrators or the authenticated user themself may even reach this check.","triggerScenarios":"Calling setQueriesAndWatches (REST UserResource) with a userId whose User entity has isDisabled()==true, while the caller passes the authorization check (admin or self).","commonSituations":"Automation scripts syncing per-user notification settings hitting a user that was recently deactivated; HR-driven offboarding disabled the account but a sync job still tries to update its watches.","solutions":["Re-enable the user account (uncheck 'Disabled' in user admin page or via UserResource) before updating queries and watches","Skip disabled users in the calling script by checking the user's disabled flag before invoking the endpoint","If the account is permanently offboarded, delete the user instead of updating their watches"],"exampleFix":"// before\nrestClient.setUserQueriesAndWatches(disabledUserId, qw);\n// after\nUser u = restClient.getUser(disabledUserId);\nif (!u.isDisabled()) restClient.setUserQueriesAndWatches(disabledUserId, qw);","handlingStrategy":"validation","validationCode":"User u = getUser(userId); if (u.isDisabled()) throw new SkipException(\"user disabled\");","typeGuard":"boolean canSetWatches(User u) { return u != null && !u.isDisabled(); }","tryCatchPattern":"try { setUserQueriesAndWatches(userId, qw); } catch (ExplicitException e) { log.warn(\"skip user {}: {}\", userId, e.getMessage()); }","preventionTips":["Check the user's disabled flag before any per-user settings update","Exclude disabled accounts from sync jobs","Keep offboarding scripts and notification-sync scripts consistent"],"tags":["rest-api","user-management","disabled-account"],"backgroundTag":"invalid-state-transition","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"}