{"record":{"id":"0b620fad857f1e24","repo":"Budibase/budibase","slug":"passwordvalidation-error","errorCode":null,"errorMessage":"${passwordValidation.error}","messagePattern":"\\$\\{passwordValidation\\.error\\}","errorType":"validation","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/backend-core/src/users/db.ts","lineNumber":139,"sourceCode":"    account?: Account\n  ): Promise<User> {\n    let { password, _id } = user\n\n    // don't require a password if the db user doesn't already have one\n    if (dbUser && !dbUser.password) {\n      opts.requirePassword = false\n    }\n\n    let hashedPassword\n    if (password && password !== dbUser?.password) {\n      if (await UserDB.isPreventPasswordActions(user, account)) {\n        throw new HTTPError(\"Password change is disabled for this user\", 400)\n      }\n\n      if (!opts.skipPasswordValidation) {\n        const passwordValidation = validatePassword(password)\n        if (!passwordValidation.valid) {\n          throw new HTTPError(passwordValidation.error, 400)\n        }\n      }\n\n      hashedPassword = opts.hashPassword ? await hash(password) : password\n    } else if (dbUser) {\n      hashedPassword = dbUser.password\n    }\n\n    // passwords are never required if sso is enforced\n    const requirePasswords =\n      opts.requirePassword && !(await UserDB.features.isSSOEnforced())\n    if (!hashedPassword && requirePasswords) {\n      throw \"Password must be specified.\"\n    }\n\n    _id = _id || dbUtils.generateGlobalUserID()\n\n    const fullUser = {","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/users/db.ts#L121-L157","documentation":"buildUser validates any newly supplied password with validatePassword() and throws the validator's message (HTTPError 400) when it fails the configured password policy (length/complexity rules). The error text is dynamic - `${passwordValidation.error}` - describing exactly which policy rule the password broke.","triggerScenarios":"save/bulkCreate -> buildUser called with a `password` that differs from the stored password and fails validatePassword (too short, no digits/symbols, etc.), unless opts.skipPasswordValidation is true.","commonSituations":"Creating users via API/scripts with weak default passwords; admin password resets that don't match the tenant policy; automated test fixtures with passwords like \"test\"; policy tightened between versions so previously valid passwords now fail.","solutions":["Supply a password that satisfies the policy: sufficiently long with mixed character classes","Inspect the error message itself - it names the specific rule that failed","Skip validation only for trusted internal flows by passing opts.skipPasswordValidation = true (rarely appropriate)","Check the tenant's configured password policy and generate conforming passwords programmatically"],"exampleFix":"// before\nawait users.save({ email, password: \"abc\" })\n// after\nawait users.save({ email, password: \"Str0ng!Passw0rd\" }) // satisfies policy","handlingStrategy":"validation","validationCode":"// validate password client-side before calling save\nfunction isValidPassword(pw: string): boolean {\n  return pw.length >= 8 && /[A-Z]/.test(pw) && /[a-z]/.test(pw) && /[0-9]/.test(pw)\n}\nif (!isValidPassword(password)) throw new Error(\"Password does not meet policy\")","typeGuard":null,"tryCatchPattern":"try {\n  await users.save(user)\n} catch (e: any) {\n  if (e?.status === 400) {\n    // e.message names the specific policy rule that failed - show it to the user\n    showPasswordPolicyHint(e.message)\n  } else throw e\n}","preventionTips":["Enforce the same password policy client-side before submitting","Generate passwords from a policy-aware generator in scripts/tests","Read the thrown message - it states the exact failed rule","Watch for policy changes across Budibase versions and update defaults"],"tags":["validation","password-policy","authentication"],"backgroundTag":"password-policy-validation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}