{"record":{"id":"e28710095c130d90","repo":"monicahq/monica","slug":"the-password-is-not-valid","errorCode":null,"errorMessage":"The password is not valid.","messagePattern":"The password is not valid\\.","errorType":"exception","errorClass":"ModelNotFoundException","httpStatus":404,"severity":"error","filePath":"app/Domains/Settings/CancelAccount/Web/Controllers/CancelAccountController.php","lineNumber":28,"sourceCode":"use Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Inertia\\Inertia;\n\nclass CancelAccountController extends Controller\n{\n    public function index()\n    {\n        return Inertia::render('Settings/CancelAccount/Index', [\n            'layoutData' => VaultIndexViewHelper::layoutData(),\n            'data' => CancelAccountViewHelper::data(),\n        ]);\n    }\n\n    public function destroy(Request $request)\n    {\n        if (! Hash::check($request->input('password'), Auth::user()->password)) {\n            throw new ModelNotFoundException('The password is not valid.');\n        }\n\n        $data = [\n            'account_id' => Auth::user()->account_id,\n            'author_id' => Auth::id(),\n        ];\n\n        CancelAccount::dispatch($data);\n\n        return response()->json([\n            'data' => route('login'),\n        ], 200);\n    }\n}\n","sourceCodeStart":10,"sourceCodeEnd":43,"githubUrl":"https://github.com/monicahq/monica/blob/e08e91734170b6bbd582cb578532c3948196124e/app/Domains/Settings/CancelAccount/Web/Controllers/CancelAccountController.php#L10-L43","documentation":"Cancelling a Monica account requires re-entering the current password. CancelAccountController::destroy() runs Hash::check(input, Auth::user()->password); on mismatch it throws ModelNotFoundException — an unconventional exception choice that surfaces as HTTP 404. On success it dispatches the queued CancelAccount job which destroys the account asynchronously.","triggerScenarios":"POSTing the cancel-account form (or equivalent API request) with a password that does not match the stored bcrypt hash: typo, stale autofill, or the password changed in another session after the form was loaded.","commonSituations":"Caps-lock/typos, password rotated elsewhere, password managers with an outdated entry, or accounts that never stored a local password (Hash::check against a null hash always fails).","solutions":["Re-enter the account's current password and resubmit","If forgotten, complete the password reset flow first, then cancel","In tests/API scripts, create the user with a known bcrypt password (Hash::make('secret')) so the check passes","Treat any non-200 (here 404) as 'not cancelled' — the destructive job only runs after a 200 response"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Client-side pre-check: never submit an empty password to the destructive endpoint\nif (typeof password !== 'string' || password.length === 0) {\n    showError('Enter your current password to cancel the account.');\n    return;\n}","typeGuard":null,"tryCatchPattern":"// HTTP client consuming the endpoint: a 404 means wrong password, account NOT deleted\nconst response = await fetch('/cancellations', { method: 'POST', body: formData });\nif (response.status === 404) {\n    showError('The password is not valid. Your account was not deleted.');\n    return; // allow retry\n}\nif (!response.ok) throw new Error('Unexpected error');\n// only a 200 means CancelAccount was dispatched","preventionTips":["Confirm the password in the UI before enabling the destructive submit button","If forgotten, use password reset first instead of retrying blind","Remember the failure is a 404 (ModelNotFoundException), not 401/422 — handle status codes accordingly","Never assume deletion succeeded without an explicit 200 response"],"tags":["monica","account-deletion","password","hash-check"],"backgroundTag":"password-verification-failed","analyzedSha":"e08e91734170b6bbd582cb578532c3948196124e","analyzedAt":"2026-08-17T01:36:49.014Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}