Budibase/budibase · error · HTTPError
Password change is disabled for this user
Error message
Password change is disabled for this user
What it means
buildUser throws an HTTPError(400) when a caller attempts to set or change a password for a user whose account is SSO-managed (isPreventPasswordActions returns true). SSO-authenticated users must change passwords via their identity provider, so Budibase blocks local password writes. This protects consistency between the local CouchDB user record and the external IdP.
Solutions
- Remove the password field from the update payload so the user keeps their existing/SSO-managed password
- Have the user change their password in the SSO identity provider instead
- Convert the user off SSO (or the tenant off SSO enforcement) before allowing local password changes
- Pass opts.skipPasswordValidation is irrelevant here; instead check UserDB.isPreventPasswordActions before sending a password
Example fix
// before
await users.save({ _id: userId, password: "newPass123" })
// after
// omit password for SSO users
const update: any = { _id: userId }
if (!(await UserDB.isPreventPasswordActions(user))) {
update.password = "newPass123"
}
await users.save(update) Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check before saving
import { UserDB } from "@budibase/backend-core/users"
const blocked = await UserDB.isPreventPasswordActions(user, account)
if (blocked) throw new Error("User is SSO-managed; omit the password field") Type guard
function isSsoManaged(user: { ssoId?: string }): boolean {
return typeof user.ssoId === "string" && user.ssoId.length > 0
} Try / catch
try {
await users.save({ _id: userId, password: newPass })
} catch (e: any) {
if (e?.status === 400 && e?.message === "Password change is disabled for this user") {
// handle SSO-managed user: notify admin / redirect to IdP
} else throw e
} Prevention
- Omit the password field on updates unless the password actually changes
- Detect SSO users (ssoId present) before sending password updates
- Surface the message to admins with a pointer to configure the password in the IdP
When it happens
Trigger: Calling save/buildUser/bulkCreate (via builtUser) with a `password` field that differs from the stored password on a user whose account is flagged SSO (isSSOUser or the tenant's account is an SSO account matching the user email).
Common situations: Admins trying to reset an SSO user's password from the admin UI or API; sync scripts bulk-updating users with password fields; self-hosted configs where SSO was enabled after password users existed; passing the full user object back to the save endpoint (echoing a stale password) instead of omitting it.
Related errors
- A new verification key is required when changing the embed…
- Cannot enforce SSO without an activated configuration
- Configuration invalid. Must contain clientID, clientSecret…
- Configuration invalid. Must contain google clientID and…
- Email is required
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/49c2bb7154fcef3d.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend-core/src/users/db.ts:133
opts: SaveUserOpts = {
hashPassword: true,
requirePassword: true,
},
tenantId: string,
dbUser?: any,
account?: Account
): Promise<User> {
let { password, _id } = user
// don't require a password if the db user doesn't already have one
if (dbUser && !dbUser.password) {
opts.requirePassword = false
}
let hashedPassword
if (password && password !== dbUser?.password) {
if (await UserDB.isPreventPasswordActions(user, account)) {
throw new HTTPError("Password change is disabled for this user", 400)
}
if (!opts.skipPasswordValidation) {
const passwordValidation = validatePassword(password)
if (!passwordValidation.valid) {
throw new HTTPError(passwordValidation.error, 400)
}
}
hashedPassword = opts.hashPassword ? await hash(password) : password
} else if (dbUser) {
hashedPassword = dbUser.password
}
// passwords are never required if sso is enforced
const requirePasswords =
opts.requirePassword && !(await UserDB.features.isSSOEnforced())
if (!hashedPassword && requirePasswords) {View on GitHub (pinned to a81a902e9a)