monicahq/monica · error · ModelNotFoundException
The password is not valid.
Error message
The password is not valid.
What it means
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.
Source
Thrown at app/Domains/Settings/CancelAccount/Web/Controllers/CancelAccountController.php:28
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Inertia\Inertia;
class CancelAccountController extends Controller
{
public function index()
{
return Inertia::render('Settings/CancelAccount/Index', [
'layoutData' => VaultIndexViewHelper::layoutData(),
'data' => CancelAccountViewHelper::data(),
]);
}
public function destroy(Request $request)
{
if (! Hash::check($request->input('password'), Auth::user()->password)) {
throw new ModelNotFoundException('The password is not valid.');
}
$data = [
'account_id' => Auth::user()->account_id,
'author_id' => Auth::id(),
];
CancelAccount::dispatch($data);
return response()->json([
'data' => route('login'),
], 200);
}
}
View on GitHub (pinned to e08e917341)
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
Defensive patterns
Strategy: try-catch
Validate before calling
// Client-side pre-check: never submit an empty password to the destructive endpoint
if (typeof password !== 'string' || password.length === 0) {
showError('Enter your current password to cancel the account.');
return;
} Try / catch
// HTTP client consuming the endpoint: a 404 means wrong password, account NOT deleted
const response = await fetch('/cancellations', { method: 'POST', body: formData });
if (response.status === 404) {
showError('The password is not valid. Your account was not deleted.');
return; // allow retry
}
if (!response.ok) throw new Error('Unexpected error');
// only a 200 means CancelAccount was dispatched Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- Could not get address book data.
- No address book found
- $e->getMessage()
- The user does not belong to the vault's account.
- Only email can be sent.
AI-assisted analysis of monicahq/monica@e08e917341 (2026-08-17).
Data as JSON: /api/errors/e28710095c130d90.
Report an issue: GitHub.