-
Notifications
You must be signed in to change notification settings - Fork 176
Description
When syncing a zero-duration Google Calendar event (VEVENT with DTSTART but no DTEND) to an iCloud CalDAV collection, vdirsyncer’s upload fails with HTTP 404 Not Found on PUT. The same calendar accepts the item if I add either:
DTENDequal toDTSTART.
Zero-duration events without DTEND are valid iCalendar per RFC 5545, and Google emits them that way by default. This appears to be an iCloud server quirk. A small, optional normalization/transform on upload would make vdirsyncer interop with iCloud out of the box.
Environment
- vdirsyncer version: vdirsyncer/0.20.0.post1.dev17+g3ba998e63.d20250920
- Python: 3.13.1
- OS: Linux
- Destination server: iCloud CalDAV
- Host: p143-caldav.icloud.com
- Server header: AppleHttpServer/7347b443149f
- Collection is shared but writable (see PROPFIND snippet below)
- Source: Google Calendar (events created in Google as “instant” events)
What happens
- vdirsyncer tries to upload an event that has no
DTEND(Google “instant” event). PUTto iCloud returns 404 Not Found, and vdirsyncer raises NotFoundError.- If I add
DTENDwith the same value as theDTSTART, thePUTreturns 201 Created and the sync proceeds.
Expected
- iCloud should accept
VEVENTwithDTSTARTonly (zero-duration), but since it doesn’t, vdirsyncer could optionally normalize zero-durationVEVENTs on upload to add an explicit end so iCloud accepts them.
Minimal reproducible ICS and curl
A) Failing: no DTEND
cat > /tmp/fail.ics <<'ICS'
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//test//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20250101T000000Z
DTSTART:20250102T000000Z
SUMMARY:Zero duration without DTEND
END:VEVENT
END:VCALENDAR
ICS
curl -i -u 'APPLE_ID:APP_SPECIFIC_PASSWORD' \
-X PUT \
-H 'If-None-Match: *' \
-H 'Content-Type: text/calendar; charset=utf-8' \
--data-binary @/tmp/fail.ics \
'https://p143-caldav.icloud.com/111.../calendars/aaa.../[email protected]'
# Returns: code=404
B) Succeeds: add DTEND equal to DTSTART
cat > /tmp/succeed_dtend_equal.ics <<'ICS'
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//test//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20250101T000000Z
DTSTART:20250102T000000Z
DTEND:20250102T000000Z
SUMMARY:Zero duration with DTEND==DTSTART
END:VEVENT
END:VCALENDAR
ICS
curl -i -u 'APPLE_ID:APP_SPECIFIC_PASSWORD' \
-X PUT \
-H 'If-None-Match: *' \
-H 'Content-Type: text/calendar; charset=utf-8' \
--data-binary @/tmp/succeed_dtend_equal.ics \
'https://p143-caldav.icloud.com/111.../calendars/aaa.../[email protected]'
# Returns: code=201
Additional observations
- Google emits zero-duration events without
DTENDby default. When I edited the event in Google to have a 15-minute duration, vdirsyncer synced it to iCloud successfully.
Proposal
I realize vdirsyncer generally avoids mutating items. However, to improve interop with iCloud, consider auto-"fixing" VEVENTs that are missing DTEND by adding a DTEND equal to DTSTART before PUT to CalDAV. This could be limited to requests that are known to being going to ical via server detection through the Server header AppleHttpServer.