pimutils / pimutils/vdirsyncer
CalDAV/iCloud: PUT 404 when VEVENT has no DTEND (zero-duration event)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.9k
- Forks
- 185
- Avg merge
- 11h 49m
- Merged PRs (30d)
- 1
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: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
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the failing and successful uploads from the minimal ICS examples, then trace vdirsyncer’s CalDAV PUT path and its handling of VEVENT data. Determine how an optional iCloud-specific normalization should be scoped and tested; done means zero-duration events upload successfully without changing other server behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100