{"record":{"id":"460a757d67548802","repo":"Mintplex-Labs/anything-llm","slug":"invalid-password","errorCode":null,"errorMessage":"Invalid password.","messagePattern":"Invalid password\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/PasswordRecovery/index.js","lineNumber":73,"sourceCode":"    const index = unmatchedHashes.findIndex((hash) =>\n      bcrypt.compareSync(code, hash)\n    );\n    if (index === -1) return false;\n    unmatchedHashes.splice(index, 1);\n    return true;\n  });\n  if (!validCodes) return { success: false, error: \"Invalid recovery codes.\" };\n\n  const { passwordResetToken, error } = await PasswordResetToken.create(\n    user.id\n  );\n  if (!!error) return { success: false, error };\n  return { success: true, resetToken: passwordResetToken.token };\n}\n\nasync function resetPassword(token, _newPassword = \"\", confirmPassword = \"\") {\n  const newPassword = String(_newPassword).trim(); // No spaces in passwords\n  if (!newPassword) throw new Error(\"Invalid password.\");\n  if (newPassword !== String(confirmPassword))\n    throw new Error(\"Passwords do not match\");\n\n  const resetToken = await PasswordResetToken.findUnique({\n    token: String(token),\n  });\n  if (!resetToken || resetToken.expiresAt < new Date()) {\n    return { success: false, message: \"Invalid reset token\" };\n  }\n\n  // JOI password rules will be enforced inside .update.\n  const { error } = await User.update(resetToken.user_id, {\n    password: newPassword,\n  });\n\n  // seen_recovery_codes is not publicly writable\n  // so we have to do direct update here\n  await User._update(resetToken.user_id, {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/PasswordRecovery/index.js#L55-L91","documentation":"Thrown by resetPassword when the trimmed new password is empty. The function trims _newPassword and rejects an empty result before any token lookup or DB write. It is the first precondition in the reset flow and prevents sending an empty password onward to User.update.","triggerScenarios":"Client submits an empty or whitespace-only password field; a malformed request body where the password value is an empty or whitespace-only string (note String(undefined).trim() yields 'undefined', so this specifically requires an empty or whitespace-only string); frontend sends the field before the user typed anything.","commonSituations":"Browser autofill leaving the field blank; automated test sending an empty string; a curl/Postman request missing the newPassword parameter.","solutions":["Ensure the client sends a non-empty password (after trim) in the newPassword field.","Add client-side validation so the reset form cannot be submitted with an empty password.","If calling resetPassword programmatically, guard with if (!newPassword?.trim()) before invoking."],"exampleFix":"// before\nawait resetPassword(token, \"   \", \"   \");\n// after\nawait resetPassword(token, \"Str0ng!Pass\", \"Str0ng!Pass\");","handlingStrategy":"validation","validationCode":"function isValidNewPassword(p) {\n  return typeof p === \"string\" && p.trim().length > 0;\n}\nif (!isValidNewPassword(newPassword)) {\n  return { success: false, message: \"Password cannot be empty.\" };\n}","typeGuard":"function isNonEmptyString(v) {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await resetPassword(token, newPassword, confirmPassword);\n} catch (e) {\n  if (/Invalid password/i.test(e.message)) {\n    return { success: false, message: \"Please provide a non-empty password.\" };\n  }\n  throw e;\n}","preventionTips":["Validate non-empty password on the client before submit.","Treat empty password as a 400, not a thrown exception, in the route handler.","Trim whitespace consistently on both client and server."],"tags":["password-recovery","validation","input"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}