mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-05-07 03:58:09 -05:00
[GH-ISSUE #1550] Reminders wrongly get ignored when multiple ones exist in a 26-hour window #6442
Closed
opened 2026-04-20 17:02:37 -05:00 by GiteaMirror
·
3 comments
No Branch/Tag Specified
main
feat-v2-foundation
spike-huma-openapi3
claude/investigate-swagger3-support-nyyUa
feat-list-view-buckets
ci-mysql-8-test
codex/analyze-codebase-for-email-task-feature
feat-project-templates
csv-import-feature
claude/email-reply-comments-wpdcQ
fix-oidc-pkce-support
fix/overview-subtasks-expand
feat/bucket-select-task-detail
feat-soft-delete-projects
claude/review-bot-design-plan-cf5C3
claude/project-scoped-api-tokens-KTqR3
claude/explore-openclaw-integration-KQEzg
claude/project-scoped-api-tokens-yv5KS
fix-duplicate-close-button
feat-list-view-sorting
feat/official-vite-sentry-plugin
feat/highlight-overdue-tasks
feat/add-enter-key-form-submission-handling
feat/TipTap-nits
feat/update-caldavtimetotimestamp-parsing
feat-phosphor-icons
wip-plans
claude/investigate-issue-2173-llKme
fix-description-text-drag
feat-custom-keyboard-shortcuts
pr-1845-ci
codex/fix-drag-and-drop-behavior-inconsistency
copilot/add-clickable-labels-for-filtering
copilot/fix-issue-1786
playwright-migration
fix-kanban-repeating-wip
copilot/fix-1498
feature/replace-axios
codex/upgrade-to-tailwind-4.1.8-using-pnpm
codex/add-cypress-test-for-avatar-types
feature/biome
feature/oxc
codex/update-flexsearch-to-0.8.205
4r6ni9-codex/fix-deprecated-sass-@import-usage
codex/fix-deprecated-sass-@import-usage
codex/add-cypress-test-for-task-list-refresh-fix
codex/fix-quick-add-magic-not-adding-tasks
codex/fix-all-type-errors
codex/fix-mimetype-for-docs.json
feature/caldav-from-scratch
feature/gh-actions-hetzner
fix-ci
feat/new-logger
jyte-better-dev-config
feat/add-team-member-with-enter
fix/button-and-icon-types
fix/notifications-component-name-collision
feature/null-time
renovate/tailwindcss-4.x
feature/unplugin-vue-router
fix/deprecated-import
feature/zod-schema
renovate/golangci-golangci-lint-1.x
fix/tiptap-editor-reactive-destructuring
release/0.24
feat/improve-add-task
fix/saved-filter-search
feat/webp-and-avif-attachment-previews
feature/migrate-back-to-bulma
fix/sass-add-missing-list-import
feature/sticky-demo-bar
fix/gantt-view-switch
feature/typesense-position-join
feature/focus-visible
dependencies/golangci-lint
feature/better-filter-syntax
fix/tiptap-task-list
renovate/github.com-golang-jwt-jwt-v4-5.x
feature/hide-forbidden-related-tasks
renovate/golang-1.x
release/0.20
release/0.17
release/0.16
release/0.15
release/0.14
v2.3.0
v2.2.2
v2.2.1
v2.2.0
v2.1.0
v2.0.0
v1.1.0
v1.0.0
v1.0.0-rc4
v1.0.0-rc3
v1.0.0-rc2
v1.0.0-rc1
v1.0.0-rc0
v0.24.6
v0.24.5
v0.24.4
v0.24.3
v0.24.2
v0.24.1
v0.24.0
v0.23.0
v0.22.1
v0.22.0
0.21.0
v0.21.0
v0.20.4
v0.20.5
v0.20.3
v0.20.2
v0.20.1
v0.20.0
v0.19.2
v0.19.1
v0.19.0
vue3
v0.18.1
v0.18.0
v0.17.1
v0.17.0
v0.16.1
v0.16.0
v0.15.1
v0.15.0
v0.14.1
v0.14.0
v0.13.1
v0.13
v0.12
v0.11
v0.10
v0.9
v0.8
v0.7
v0.6
v0.5
v0.4
v0.3
v0.2
v0.1
Labels
Clear labels
area/api
area/attachments
area/auth
area/avatars
area/backup-restore
area/caldav
area/calendar-view
area/comments
area/config
area/database
area/desktop
area/docker
area/email
area/favorites
area/filters
area/frontend
area/gantt
area/i18n
area/import-export
area/internal-code
area/kanban
area/labels
area/list-view
area/mobile
area/notifications
area/permissions
area/projects
area/pwa
area/recurring-tasks
area/reminders
area/search
area/shortcuts
area/subtasks
area/sync
area/table-view
area/task-editor
area/task-metadata
area/task-relations
area/teams
area/theming
area/time-tracking
area/typesense
area/views
area/webhooks
bug
changes requested
concern/accessibility
concern/performance
concern/regression
concern/ux
confirmed
db/mysql
dependencies
enhancement
good first issue
help wanted
integration/inbound
integration/outbound
kind/bug
kind/feature
needs reproduction
pull-request
question
security
support
upstream issue
waiting for reply
wontfix
Mirrored from GitHub Pull Request
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/vikunja#6442
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @shibijm on GitHub (Sep 26, 2025).
Original GitHub issue: https://github.com/go-vikunja/vikunja/issues/1550
Description
When a task's reminders are being evaluated, if more than one reminder exists for that task between now-12h and now+1m+14h, only the first reminder from the database is considered, and a flag is set to not consider further reminders, regardless of the validity of the first reminder. If there are subsequent reminders that are valid and due to be sent, they get wrongly ignored.
Scenario:
getTasksWithRemindersDueAndTheirUsersruns at 5 PM through the scheduled cron function that runs every minute.seen[r.TaskID][u.User.ID]gets set totruefor the above-mentioned task and your user.ifstatement checks whether the 9 AM reminder is within the current 1-minute window. 9 AM is not within the 1-minute window at 5 PM, so it gets ignored correctly.seenmap because of the previous 9 AM reminder, despite it being out-of-range. Because of this, the 5 PM reminder doesn't get checked and hence gets dropped silently, even though a notification for it is supposed to be sent right now.Steps to reproduce:
To reproduce this issue easily, you can create a task and set a reminder at each minute in the next 5 minutes. After those 5 minutes, you would have received only 1 notification for only the 1st reminder that was created, instead of all 5 of them.
Fix:
This issue can be fixed by moving the
seen[r.TaskID][u.User.ID] = trueline to be inside theifblock that checks whether the reminder is within the current 1-minute window. That way, as intended, the relevant taskID+userID combo in theseenmap will exist only if a previously-processed reminder was actually in-range and eligible for being sent now.Alternative fix through other improvements:
I might be missing something or misunderstanding some intended logic so correct me if I'm wrong:
The reminder's time instant stored in the database and parsed by the backend, regardless of its timezone or the server's timezone, already correctly matches the time instant represented by the local time inputted by the user on the frontend, so all the timezone-related code in this function seems unnecessary.
In fact, the timezone-related code doesn't seem to be affecting the behaviour of this function at all:
The
tzin the function is being used only once for theactualReminder := r.Reminder.In(tz)line, but this does not affect any further logic, because as mentioned in Go's documentation fortime.Time.In, this just sets the timezone/location for display purposes so it doesn't change the underlying time value. Usingr.Reminderinstead ofactualReminderfor the 1-minute window check yields the same result.From Go's docs:
Removing all the timezone-related code from this function would not affect the current behaviour of it, and the database can be queried for only reminders in the current 1-minute window instead of a 26-hour window. Through this change, in addition to unnecessary overhead getting removed, the main issue of in-range reminders getting ignored will also be fixed.
Vikunja Version
v1.0.0-rc2
Browser and version
Not applicable
Can you reproduce the bug on the Vikunja demo site?
Reminder notifications don't seem to work at all on the demo site
Screenshots
Not applicable
@kolaente commented on GitHub (Sep 29, 2025):
Thanks for the issue and the detailed analysis. I've opened a draft PR with a fix here: https://github.com/go-vikunja/vikunja/pull/1564
The goal with this logic is to allow users to receive a reminder in their time zone. This means if I set a reminder for 9 AM, every user will get it at 9 AM in their time zone, regardless of what that is.
@shibijm commented on GitHub (Sep 29, 2025):
Thank you for the quick fix!
Hmm, that's not the current behaviour of the function, and I don't think it can be made to work that way without bigger changes.
The
reminderfield in thetask_reminderstable is a specific point in time. If my computer's/browser's timezone is UTC+05:30 and I set a reminder at 9 AM, it gets stored in the table as 03:30 UTC (the frontend also transmits it to the backend in UTC). From that UTC time, for the goal you mentioned, we need to determine different points in time that correspond to 9 AM in different timezones. To do that, we need the timezone of the user who created the reminder, to calculate the offsets of other users' timezones relative to that. These offsets can then be applied to the reminder by changing the underlying time value to determine different points in time that match 9 AM in different users' timezones.The required timezone of the user who created the reminder is not being stored in that table. The ID of the user who created the reminder isn't being stored either, so you can't get the required timezone from the
userstable. If it's meant to be based on the timezone of the user who created the task, then thecreated_by_idfield in thetaskstable can be used to join withusers, but nothing like that is being done for this purpose in that function. The frontend would also have to be changed to reflect the reminder's time properly, since currently it displays the local time without any offsets, directly corresponding to the UTC time stored in the database.I also think that the intended behaviour (which isn't currently the case) might not be desirable for many use cases. For example, if a reminder is set for a specific event that's taking place at a specific time, like an online meeting, that reminder should be sent at that exact specific time for all users without considering their timezones.
Regardless of the intended behaviour, what I was saying in the main issue post is that the current timezone logic in the function is redundant because it's not affecting any behaviour at all. See the example below:
https://go.dev/play/p/FzDT_8gRGVh
Code
Output
@kolaente commented on GitHub (Oct 1, 2025):
Thanks for the explanation! It might be that I missed that - at least what I was wanting to achieve with the feature is what I outlined above. The feature was also one of the first in Vikunja, very likely there are bugs with it.
Note that the idea was for every user who gets the reminder to have it in their time zone, not in the one of the user who created the reminder.
Another use case I want is (and that is working right now) to incorporate daylight savings, especially for repeating tasks. When I set a task to repeat weekly and it has a reminder for 9:00, I want that to happen every time at 9:00.
I think there are a few ways to solve this:
But you bring up a valid point: if there is a deadline at a certain time, I want that to be the same point in time everywhere, regardless of the time zone.
And the use case "multiple people work on the same thing in different time zones" is probably an edge case anyway. What isn't, are daylight savings, so that should be something we need to pay attention to anyways.