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:
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).
PUT to iCloud returns 404 Not Found, and vdirsyncer raises NotFoundError.
- If I add
DTEND with the same value as the DTSTART, the PUT returns 201 Created and the sync proceeds.
Expected
- iCloud should accept
VEVENT with DTSTART only (zero-duration), but since it doesn’t, vdirsyncer could optionally normalize zero-duration VEVENTs 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:test-zero-no-end@example.com
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.../test-zero-no-end@example.com.ics'
# 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:test-zero-dtend-equals-dtstart@example.com
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.../test-zero-dtend-equals-dtstart@example.com.ics'
# Returns: code=201
Additional observations
- Google emits zero-duration events without
DTEND by 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.
When syncing a zero-duration Google Calendar event (
VEVENTwithDTSTARTbut noDTEND) to an iCloud CalDAV collection, vdirsyncer’s upload fails with HTTP 404 Not Found onPUT. The same calendar accepts the item if I add either:DTENDequal toDTSTART.Zero-duration events without
DTENDare 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
What happens
DTEND(Google “instant” event).PUTto iCloud returns 404 Not Found, and vdirsyncer raises NotFoundError.DTENDwith the same value as theDTSTART, thePUTreturns 201 Created and the sync proceeds.Expected
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
DTENDB) Succeeds: add
DTENDequal toDTSTARTAdditional observations
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 missingDTENDby adding aDTENDequal toDTSTARTbeforePUTto CalDAV. This could be limited to requests that are known to being going to ical via server detection through the Server headerAppleHttpServer.