theonedev/onedev · error · ExplicitException

Cannot set password for disabled account

Error message

Cannot set password for disabled account

What it means

The setPassword REST endpoint (POST /users/{userId}/password) refuses to set a password on a disabled account. OneDev intentionally blocks credential changes for accounts that are currently disabled, since the account cannot log in anyway and the change would be unauditable in normal use.

Source

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

		if (!SecurityUtils.isAdministrator()) 
			throw new UnauthorizedException();
		if (userId <= User.ROOT_ID)		
			throw new BadRequestException("Should only convert normal users to service accounts");
		var user = userService.load(userId);
		userService.convertToServiceAccount(user);

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

		return Response.ok().build();
    }
	
	@Api(order=2000)
	@Path("/{userId}/password")
    @POST
    public Response setPassword(@PathParam("userId") Long userId, @Password(checkPolicy=true) @NotEmpty String password) {
    	User user = userService.load(userId);
		if (user.isDisabled()) {
			throw new ExplicitException("Cannot set password for disabled account");
		} else if (user.getType() != ORDINARY) {
			throw new ExplicitException("Cannot set password for service or AI account");
		} if (SecurityUtils.isAdministrator()) {
			user.setPassword(passwordService.encryptPassword(password));
			userService.update(user, null);
			if (!getAuthUser().equals(user)) 
				auditService.audit(null, "changed password of account \"" + user.getName() + "\" via RESTful API", null, null);
			return Response.ok().build();
		} else if (user.equals(getAuthUser())) {
			if (user.getPassword() == null) {
				throw new ExplicitException("The user is currently authenticated via external system, "
						+ "please change password there instead");
			} else {
				user.setPassword(passwordService.encryptPassword(password));
				userService.update(user, null);
				return Response.ok().build();
			}			
    	} else {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Re-enable the user account first (enable in UI or POST /users/{id}/enable) then set the password
  2. Skip disabled users in bulk password-reset scripts by filtering on the user's enabled status
  3. Check the user's disabled state via GET /users/{userId} before attempting the password change

Example fix

// before
await rest.post(`/users/${id}/password`, {password}); // 400 if disabled
// after
const user = await rest.get(`/users/${id}`);
if (!user.disabled) {
  await rest.post(`/users/${id}/password`, {password});
}
Defensive patterns

Strategy: validation

Validate before calling

const user = await rest.get(`/users/${userId}`); if (user.disabled) throw new Error('Cannot set password for a disabled account');

Type guard

function canSetPassword(user) { return !user.disabled && user.type === 'ORDINARY'; }

Try / catch

try { await rest.post(`/users/${id}/password`, {password}); } catch (e) { if (e.status === 400 && /disabled account/.test(e.message)) { /* re-enable first or skip */ } else throw e; }

Prevention

When it happens

Trigger: Calling POST /rest/v1/users/{userId}/password for a user whose account is disabled (user.isDisabled() == true).

Common situations: Provisioning flows that reset passwords for all users in a batch including disabled ones; helpdesk resetting a password for a suspended account; syncing passwords for inactive users.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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