theonedev/onedev · error · ExplicitException
Cannot set password for service or AI account
Error message
Cannot set password for service or AI account
What it means
Passwords can only be set on ordinary user accounts. If the target user's type is not ORDINARY — e.g. a service account or an AI account — the setPassword endpoint rejects the request. Service/AI accounts are not interactive-login accounts and must not hold local passwords.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/UserResource.java:491
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 {
throw new UnauthorizedException();
}View on GitHub (pinned to d44925c47c)
Solutions
- Verify the target account's type is ORDINARY before calling the password endpoint
- Remove service/AI accounts from bulk password-set operations
- If credential-like access is needed for a service account, use access tokens instead of passwords
Example fix
// before
await rest.post(`/users/${svc.id}/password`, {password}); // 400: not ORDINARY
// after
if (svc.type === 'ORDINARY') {
await rest.post(`/users/${svc.id}/password`, {password});
} else {
await rest.post(`/users/${svc.id}/tokens`, ...); // access token instead
} Defensive patterns
Strategy: validation
Validate before calling
const user = await rest.get(`/users/${userId}`); if (user.type !== 'ORDINARY') throw new Error('Passwords can only be set on ordinary accounts'); Type guard
function isOrdinaryUser(user) { return user.type === 'ORDINARY'; } Try / catch
try { await rest.post(`/users/${id}/password`, {password}); } catch (e) { if (e.status === 400 && /service or AI account/.test(e.message)) { /* use access tokens instead */ } else throw e; } Prevention
- Only target ORDINARY accounts in password scripts
- Use access tokens for service/AI accounts instead of passwords
- Verify account type before any credential mutation
When it happens
Trigger: Calling POST /rest/v1/users/{userId}/password where the user's type is SERVICE or AI instead of ORDINARY.
Common situations: Scripts that iterate all users and try to set passwords on service accounts; mistaking a service account id for a normal user's; automation tooling that syncs credentials across all account types.
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
- Cannot set password for disabled account
- The user is currently authenticated via external system, ple
- Cannot set AI setting for non AI account
- Cannot reset two factor authentication for service or AI acc
- Reviewer not found:
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/0da6dcedccc8b264.
Report an issue: GitHub.