iOS CalDAV works but breaks as soon as recurring task is created in Vikunja #2223

Closed
opened 2026-03-22 13:58:09 -05:00 by GiteaMirror · 5 comments
Owner

Originally created by @harrystuart on GitHub (May 6, 2025).

Description

Hello, Vikunja makes clear that iOS CalDAV is not strongly supported. Support, however, would enable many users to sync with iOS Reminders which would be an absolute godsend.

I have successfully connected to and used Vikunja CalDAV with iOS Reminders. However, as soon as I create a recurring task in Vikunja, CalDAV completely breaks.

Below is the self-contained experiment I ran:

  1. docker-compose up | tee vikunja.log
  2. Logged into web app using Test
  3. Connected to CalDAV with iOS
  4. Created Test Web Task 1 in web app
  5. Test Web Task 1 displayed in iOS Reminders
  6. Created Test iOS Task 1 in iOS Reminders
  7. Test iOS Task 1 displayed in web app
  8. Created Test Web Recurring Task 1 with daily recurrence since completion (and later added due tomorrow) in web app
  9. Test Web Recurring Task 1 not displayed in iOS Reminders
  10. Created Test Web Task 2 in web app
  11. Test Web Task 2 not displayed in iOS Reminders
  12. Created Test iOS Task 2 in iOS Reminders
  13. Test iOS Task 2 displayed in web app
  14. Deleted CalDAV account from iOS
  15. Restarted iOS
  16. Connected to CalDAV with iOS
  17. No tasks displayed in iOS Reminders

My docker-compose.yml looks like so:

vikunja:
  image: vikunja/vikunja
  environment:
    VIKUNJA_DATABASE_TYPE: sqlite
    VIKUNJA_SERVICE_PUBLICURL: https://vikunja.hstu.net
    VIKUNJA_LOG_LEVEL: DEBUG
    VIKUNJA_LOG_EVENTS: stdout
    VIKUNJA_LOG_EVENTSLEVEL: DEBUG
  ports:
    - 3456:3456
  volumes:
    - /storage/enc/docker/vikunja/files:/app/vikunja/files
    - /storage/enc/docker/vikunja/db:/db

I have attached the logs output. I would greatly appreciate some assistance in parsing these log files and trying to arrest the offending backend logic - I am not a Go dev but am happy to do what I can if pointed in the right direction.

vikunja.log

Vikunja Version

v0.24.6

Browser and version

No response

Can you reproduce the bug on the Vikunja demo site?

No

Screenshots

Image

Originally created by @harrystuart on GitHub (May 6, 2025). ### Description Hello, Vikunja makes clear that iOS CalDAV is not strongly supported. Support, however, would enable many users to sync with iOS Reminders which would be an absolute godsend. I have successfully connected to and used Vikunja CalDAV with iOS Reminders. However, as soon as I create a recurring task in Vikunja, CalDAV completely breaks. Below is the self-contained experiment I ran: 1. `docker-compose up | tee vikunja.log` 2. Logged into web app using Test 3. Connected to CalDAV with iOS 4. Created Test Web Task 1 in web app 5. Test Web Task 1 displayed in iOS Reminders 6. Created Test iOS Task 1 in iOS Reminders 7. Test iOS Task 1 displayed in web app 8. Created Test Web Recurring Task 1 with daily recurrence since completion (and later added due tomorrow) in web app 9. Test Web Recurring Task 1 not displayed in iOS Reminders 10. Created Test Web Task 2 in web app 11. Test Web Task 2 not displayed in iOS Reminders 12. Created Test iOS Task 2 in iOS Reminders 13. Test iOS Task 2 displayed in web app 14. Deleted CalDAV account from iOS 15. Restarted iOS 16. Connected to CalDAV with iOS 17. No tasks displayed in iOS Reminders My `docker-compose.yml` looks like so: ```yaml vikunja: image: vikunja/vikunja environment: VIKUNJA_DATABASE_TYPE: sqlite VIKUNJA_SERVICE_PUBLICURL: https://vikunja.hstu.net VIKUNJA_LOG_LEVEL: DEBUG VIKUNJA_LOG_EVENTS: stdout VIKUNJA_LOG_EVENTSLEVEL: DEBUG ports: - 3456:3456 volumes: - /storage/enc/docker/vikunja/files:/app/vikunja/files - /storage/enc/docker/vikunja/db:/db ``` I have attached the logs output. I would greatly appreciate some assistance in parsing these log files and trying to arrest the offending backend logic - I am not a Go dev but am happy to do what I can if pointed in the right direction. [vikunja.log](https://github.com/user-attachments/files/20073487/vikunja.log) ### Vikunja Version v0.24.6 ### Browser and version _No response_ ### Can you reproduce the bug on the Vikunja demo site? No ### Screenshots ![Image](https://github.com/user-attachments/assets/c82c5fb2-3b19-45ad-a2c6-0d5c7bcdd7e4)
GiteaMirror added the area/caldav label 2026-03-22 13:58:09 -05:00
Author
Owner

@harrystuart commented on GitHub (May 7, 2025):

Okay, I've dug a bit further...

The following task IS NOT displayed by iOS:

BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:
PRODID:-//Vikunja Todo App//EN
BEGIN:VTODO
UID:3e7b76d5-386e-472c-ba7b-0f093cc396d5
DTSTAMP:20250507T093827Z
SUMMARY:Test Recurring
DESCRIPTION:<p></p>
CREATED:20250507T091433Z
RRULE:FREQ=SECONDLY;INTERVAL=86400
LAST-MODIFIED:20250507T093827Z
END:VTODO
END:VCALENDAR

The following task IS displayed by iOS:

BEGIN:VCALENDAR
VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:
PRODID:-//Vikunja Todo App//EN
BEGIN:VTODO
UID:3e7b76d5-386e-472c-ba7b-0f093cc396d5
DTSTAMP:20250507T093851Z
SUMMARY:Test Recurring
DESCRIPTION:<p></p>
CREATED:20250507T091433Z
RRULE:FREQ=MONTHLY;BYMONTHDAY=01
LAST-MODIFIED:20250507T093851Z
END:VTODO
END:VCALENDAR

So, iOS Reminders doesn't seem to understand the concept of FREQ=SECONDLY... How to get around this lol?

See https://developer.apple.com/documentation/eventkit/ekrecurrencefrequency

It seems like all Default FREQ=SECONDLY is used ubiquitously for Default and From completion date repeat modes. Would a PR ever be accepted if it instead mapped RRULE:FREQ=SECONDLY;INTERVAL=604800 to RRULE:FREQ=WEEKLY;INTERVAL=1 and so forth? I don't think you'd lose anything but you would then be able to support recurring tasks in iOS - that's pretty huge.

@harrystuart commented on GitHub (May 7, 2025): Okay, I've dug a bit further... The following task IS NOT displayed by iOS: ``` BEGIN:VCALENDAR VERSION:2.0 METHOD:PUBLISH X-PUBLISHED-TTL:PT4H X-WR-CALNAME: PRODID:-//Vikunja Todo App//EN BEGIN:VTODO UID:3e7b76d5-386e-472c-ba7b-0f093cc396d5 DTSTAMP:20250507T093827Z SUMMARY:Test Recurring DESCRIPTION:<p></p> CREATED:20250507T091433Z RRULE:FREQ=SECONDLY;INTERVAL=86400 LAST-MODIFIED:20250507T093827Z END:VTODO END:VCALENDAR ``` The following task IS displayed by iOS: ``` BEGIN:VCALENDAR VERSION:2.0 METHOD:PUBLISH X-PUBLISHED-TTL:PT4H X-WR-CALNAME: PRODID:-//Vikunja Todo App//EN BEGIN:VTODO UID:3e7b76d5-386e-472c-ba7b-0f093cc396d5 DTSTAMP:20250507T093851Z SUMMARY:Test Recurring DESCRIPTION:<p></p> CREATED:20250507T091433Z RRULE:FREQ=MONTHLY;BYMONTHDAY=01 LAST-MODIFIED:20250507T093851Z END:VTODO END:VCALENDAR ``` So, iOS Reminders doesn't seem to understand the concept of `FREQ=SECONDLY`... How to get around this lol? See https://developer.apple.com/documentation/eventkit/ekrecurrencefrequency It seems like all Default `FREQ=SECONDLY` is used ubiquitously for `Default` and `From completion date` repeat modes. Would a PR ever be accepted if it instead mapped `RRULE:FREQ=SECONDLY;INTERVAL=604800` to `RRULE:FREQ=WEEKLY;INTERVAL=1` and so forth? I don't think you'd lose anything but you would then be able to support recurring tasks in iOS - that's pretty huge.
Author
Owner

@harrystuart commented on GitHub (May 8, 2025):

I fixed this issue by changing pkg/caldav/caldav.go from

...
if t.RepeatAfter > 0 || t.RepeatMode == models.TaskRepeatModeMonth {
			if t.RepeatMode == models.TaskRepeatModeMonth {
				caldavtodos += `
RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02") // Day of the month
			} else {
				caldavtodos += `
RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10)
			}
		}
...

to

...
if t.RepeatAfter > 0 || t.RepeatMode == models.TaskRepeatModeMonth {
			switch {
		
			// 1) explicit “monthly” mode (already correct)
			case t.RepeatMode == models.TaskRepeatModeMonth:
				caldavtodos += `
RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02")
		
			// 2) exact multiple of a week
			case t.RepeatAfter%604800 == 0:
				weeks := t.RepeatAfter / 604800
				if weeks < 1 {
					weeks = 1
				}
				caldavtodos += `
RRULE:FREQ=WEEKLY;INTERVAL=` + strconv.FormatInt(weeks, 10)
		
			// 3) exact multiple of a day
			case t.RepeatAfter%86400 == 0:
				days := t.RepeatAfter / 86400
				if days < 1 {
					days = 1
				}
				caldavtodos += `
RRULE:FREQ=DAILY;INTERVAL=` + strconv.FormatInt(days, 10)
		
			// 4) everything else stays as seconds so existing logic keeps working
			default:
				caldavtodos += `
RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10)
			}
		}
...

@kolaente would this be a change you're open to if I raise a PR? Cheers

@harrystuart commented on GitHub (May 8, 2025): I fixed this issue by changing `pkg/caldav/caldav.go` from ```go ... if t.RepeatAfter > 0 || t.RepeatMode == models.TaskRepeatModeMonth { if t.RepeatMode == models.TaskRepeatModeMonth { caldavtodos += ` RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02") // Day of the month } else { caldavtodos += ` RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10) } } ... ``` to ```go ... if t.RepeatAfter > 0 || t.RepeatMode == models.TaskRepeatModeMonth { switch { // 1) explicit “monthly” mode (already correct) case t.RepeatMode == models.TaskRepeatModeMonth: caldavtodos += ` RRULE:FREQ=MONTHLY;BYMONTHDAY=` + t.DueDate.Format("02") // 2) exact multiple of a week case t.RepeatAfter%604800 == 0: weeks := t.RepeatAfter / 604800 if weeks < 1 { weeks = 1 } caldavtodos += ` RRULE:FREQ=WEEKLY;INTERVAL=` + strconv.FormatInt(weeks, 10) // 3) exact multiple of a day case t.RepeatAfter%86400 == 0: days := t.RepeatAfter / 86400 if days < 1 { days = 1 } caldavtodos += ` RRULE:FREQ=DAILY;INTERVAL=` + strconv.FormatInt(days, 10) // 4) everything else stays as seconds so existing logic keeps working default: caldavtodos += ` RRULE:FREQ=SECONDLY;INTERVAL=` + strconv.FormatInt(t.RepeatAfter, 10) } } ... ``` @kolaente would this be a change you're open to if I raise a PR? Cheers
Author
Owner

@kolaente commented on GitHub (May 9, 2025):

Would love a PR with this!

@kolaente commented on GitHub (May 9, 2025): Would love a PR with this!
Author
Owner

@kolaente commented on GitHub (Aug 3, 2025):

hey @harrystuart are you still interested in a PR?

@kolaente commented on GitHub (Aug 3, 2025): hey @harrystuart are you still interested in a PR?
Author
Owner

@kolaente commented on GitHub (Aug 4, 2025):

Fixed in https://github.com/go-vikunja/vikunja/pull/1230, please check with the next unstable build (should be ready for deployment in ~30min, also on try).

@kolaente commented on GitHub (Aug 4, 2025): Fixed in https://github.com/go-vikunja/vikunja/pull/1230, please check with the next unstable build (should be ready for deployment in ~30min, also on [try](https://try.vikunja.io)).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vikunja#2223