"Create annual reminder" on a life event silently fails for every built-in life event type
⚠️ This issue respects the following points: ⚠️
- This is a bug, not a question or a configuration/webserver/proxy issue.
- This issue is not already reported on Github (I've searched it).
- I agree to follow Monica's Code of Conduct.
Bug description
Checking "create annual reminder" when adding a life event silently does nothing if the life event uses one of Monica's built-in/default life event types (e.g. "Got married," "New job," "Moved," etc. — any type you didn't create yourself under Settings → Life Event Types). The life event itself saves normally, but no row is ever created in reminders, and no error is shown anywhere in the UI.
Steps to reproduce
- Fresh (or existing) account using the built-in life event categories/types seeded at account creation.
- Add a life event to any contact, picking one of the built-in types (e.g. "Got married" under Relationship).
- Check "Create a reminder for this every year."
- Save.
- Check the contact's upcoming reminders (dashboard, or GET /api/reminders/upcoming/{month}), and the reminders table directly.
Expected behavior
Expected: a reminders row exists for this life event, frequency_type = year, and it appears in the upcoming-reminders list once its date is within range.
Actual: no reminders row is ever created. life_events.reminder_id stays NULL. No error is surfaced in the browser.
Root cause
- PopulateLifeEventsTable::feedLifeEventType() (app/Services/Auth/Population/PopulateLifeEventsTable.php) seeds every built-in LifeEventType for an account with only default_life_event_type_key set — name is left NULL by design, since the display string comes from a translation lookup (people.life_event_sentence_{key}), not the name column.
- CreateLifeEvent::addYearlyReminder() (app/Services/Contact/LifeEvent/CreateLifeEvent.php) builds the reminder's data with 'title' => $lifeEvent->lifeEventType->name. For any built-in type this is NULL.
- CreateReminder::rules() (app/Services/Contact/Reminder/CreateReminder.php) requires 'title' => 'required|string|max:100000', so reminder creation throws a ValidationException.
- This happens after $lifeEvent->save() has already run, so the life event persists with reminder_id still NULL — there's no transaction wrapping the two operations.
- In the web UI, LifeEventsController::store() catches the exception generically and returns back()->withErrors(...) (a redirect), but the request is submitted via axios.post() from CreateLifeEvent.vue with no .catch() handler — so the failure is swallowed client-side with no visible error to the user.
- Confirmed directly against the DB: 11 life events created via the UI (all built-in types, "create reminder" checked each time) all have reminder_id = NULL, and none exist in reminders.
- Also reproduced directly via the REST API (bypassing the browser entirely): POST /api/lifeevents with has_reminder: true on a built-in life_event_type_id returns: {"error": {"message": ["The title field is required."], "error_code": 32}}
- confirming the failure is server-side, not a frontend issue.
Suggested fix
In CreateLifeEvent::addYearlyReminder(), fall back to the resolved/translated display name instead of the raw name column when it's null (mirroring what the Vue frontend already does for display). Alternatively/additionally, wrap the reminder creation in the same DB transaction as the life event save so a failure rolls back the life event too instead of leaving an inconsistent reminder_id = NULL row — and surface the error to the user either way (add a .catch() in CreateLifeEvent.vue, and/or have LifeEventsController::store() return a JSON error response instead of a redirect, since it's invoked via axios, not a normal form submit).
Workaround
Create a custom life event type (Settings → Life Event Types) and use that instead of a built-in type — custom types require and store a real name, so they don't hit the null-title path. Confirmed working.
Environment
Your own self-hosted instance (monica v4)
Version of Monica
4.1.2
Installation method
Docker image
Web server
None
Database engine version
MariaDB
Additional info
No response
Source: monicahq/monica