theonedev/onedev · error · BadRequestException

Should only disable normal users

Error message

Should only disable normal users

What it means

Thrown by UserResource.disableUser when the target userId is not a normal user. OneDev reserves ids <= User.ROOT_ID (system/root accounts, e.g. id 1 and built-in users); these cannot be disabled, so the endpoint rejects them with 400 Bad Request.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java:438

		if (!getAuthUser().equals(user)) {
			var newAuditContent = VersionedXmlDoc.fromBean(data).toXML();
			auditService.audit(null, "changed account \"" + user.getName() + "\" via RESTful API", oldAuditContent, newAuditContent);
		}
		
		return Response.ok().build();
    }

	@Api(order=1960, description="Disable user")
	@Path("/{userId}/disable")
    @POST
    public Response disableUser(@PathParam("userId") Long userId) {
		if (!subscriptionService.isSubscriptionActive())
			throw new NotAcceptableException("This operation requires active subscription");
		if (!SecurityUtils.isAdministrator()) 
			throw new UnauthorizedException();
		
		if (userId <= User.ROOT_ID)		
			throw new BadRequestException("Should only disable normal users");
		var user = userService.load(userId);
		userService.disable(user);

		auditService.audit(null, "disabled account \"" + user.getName() + "\" via RESTful API", null, null);

		return Response.ok().build();
    }

	@Api(order=1970, description="Enable user")
	@Path("/{userId}/enable")
    @POST
    public Response enableUser(@PathParam("userId") Long userId) {
		if (!subscriptionService.isSubscriptionActive())
			throw new NotAcceptableException("This operation requires active subscription");
		if (!SecurityUtils.isAdministrator()) 
			throw new UnauthorizedException();
		if (userId <= User.ROOT_ID)		
			throw new BadRequestException("Should only enable normal users");

View on GitHub (pinned to d44925c47c)

Solutions

  1. Only call disable for normal users — filter userId > User.ROOT_ID (e.g. > 1).
  2. Check the user's type before disabling (skip built-in/system accounts).
  3. Fix automation loops to start from real user ids.
  4. Disable the offending account via admin UI if it truly is a normal user with a low id.

Example fix

// before
for (long id = 1; id <= maxId; id++) disableUser(id); // hits id=1 -> 400
// after
for (long id = User.ROOT_ID + 1; id <= maxId; id++)
    if (isNormalUser(id)) disableUser(id);
Defensive patterns

Strategy: validation

Validate before calling

if (userId <= 1 /* User.ROOT_ID */)
    throw new IllegalArgumentException("Cannot disable system/root user id " + userId);

Type guard

boolean isNormalUser(long userId) { return userId > User.ROOT_ID; }

Try / catch

try { client.disableUser(userId); }
catch (BadRequestException e) { log.error("Refusing to disable reserved user id " + userId); }

Prevention

When it happens

Trigger: POST /rest/users/{userId}/disable with userId <= User.ROOT_ID — e.g. disabling user id 1 (root) or another reserved/system account.

Common situations: Looping over all user ids starting from 1; blindly disabling accounts returned by broad queries that include system users.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/b10a85397f59bc67. Report an issue: GitHub.