{"record":{"id":"6c5f93909e55f52a","repo":"Mintplex-Labs/anything-llm","slug":"passwords-do-not-match","errorCode":null,"errorMessage":"Passwords do not match","messagePattern":"Passwords do not match","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/PasswordRecovery/index.js","lineNumber":75,"sourceCode":"    );\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, {\n    seen_recovery_codes: false,\n  });","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/PasswordRecovery/index.js#L57-L93","documentation":"Thrown by resetPassword when the trimmed new password does not equal the trimmed confirmPassword string. This is a standard confirm-password equality check performed before token lookup and password update. Both values are coerced to strings, so type mismatches alone won't trigger it — only differing content will.","triggerScenarios":"The two password fields contain different characters after trimming; confirmPassword is undefined (String(undefined)='undefined') while newPassword is a real password; the frontend sent confirmPassword under a different key name.","commonSituations":"User typo between the two fields; frontend bug only sending one field; client concatenating or transforming one value; copy-paste error.","solutions":["Re-enter both password fields identically and resubmit.","Check the client payload includes both newPassword and confirmPassword with matching values.","Verify the field names sent in the request body exactly match the parameter names the route expects.","Add a client-side equality check to give immediate feedback before submit."],"exampleFix":"// before\nawait resetPassword(token, \"Str0ng!Pass\", \"Str0ng!Passs\");\n// after\nawait resetPassword(token, \"Str0ng!Pass\", \"Str0ng!Pass\");","handlingStrategy":"validation","validationCode":"if (String(newPassword).trim() !== String(confirmPassword).trim()) {\n  return { success: false, message: \"Passwords do not match.\" };\n}","typeGuard":"function passwordsMatch(a, b) {\n  return typeof a === \"string\" && typeof b === \"string\" && a.trim() === b.trim();\n}","tryCatchPattern":"try {\n  return await resetPassword(token, newPassword, confirmPassword);\n} catch (e) {\n  if (/Passwords do not match/i.test(e.message)) {\n  return { success: false, message: \"Passwords do not match.\" };\n  }\n  throw e;\n}","preventionTips":["Add a client-side equality check with a 'show password' toggle to catch typos.","Ensure both fields are sent with the exact parameter names the route expects.","Avoid transforming one field (e.g. hashing) on the client but not the other."],"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"}