iCloud: URL.join raises "can't be joined" when REPORT hrefs use caldav.icloud.com after client.url was rewritten to the pNN partition host
Maintainer thường phản hồi trong vòng 1 ngày
Một pull request liên quan đã được merge.
- #733 của @tobixen — đã merge
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 52/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- python
- Lĩnh vực
- backend, networking
Hướng nghiên cứu
Start by reading caldav/lib/url.py around URL.join, caldav/davobject.py around DAVObject.__init__, and the iCloud handling in collection.py near calendar_home_set and _post_request_report_build_resultlist. Use the provided no-network reproduction to confirm the hostname mismatch, then add a regression test for an absolute iCloud href on the alternate host. Done means same-service iCloud URLs are handled without weakening rejection of unrelated host mismatches.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Disclosure (per AI-POLICY.md): this bug was hit on my Home Assistant install. The diagnosis, the reproduction script and the suggested fix below were produced with Claude (Anthropic, via Claude Code); I've checked the results against my live setup. I'm happy to answer questions and test a fix.
What happens
With iCloud, searches on a calendar intermittently fail with:
ValueError: https://p49-caldav.icloud.com:443/12345678/calendars/ can't be joined with https://caldav.icloud.com/12345678/calendars/<calendar-uuid>/<event-uuid>.ics
Traceback (caldav 3.3.0a1, as pinned by Home Assistant 2026.10.0; the same code is on master at b8497e9):
File "caldav/collection.py", line 1864, in search
File "caldav/search.py", line 999, in search
...
File "caldav/collection.py", line 1663, in _request_report_build_resultlist
File "caldav/collection.py", line 1640, in _post_request_report_build_resultlist
File "caldav/calendarobjectresource.py", line 171, in __init__
File "caldav/davobject.py", line 108, in __init__
File "caldav/lib/url.py", line 264, in join
raise ValueError("%s can't be joined with %s" % (self, path))
Once it starts, every search fails until the client is rebuilt. In Home Assistant that means the calendar entity is unavailable until a restart. I saw two windows of about 1–2.5 hours on one day.
Why
- The client is created with
url="https://caldav.icloud.com". calendar-home-setcomes back on the account's partition host (https://p49-caldav.icloud.com:443/12345678/calendars/). The setter inPrincipal.calendar_home_set(the "Here be dragons" block incollection.py) then rewritesclient.urlto that host.- iCloud does not always use the same host in its responses. When I query the generic host, every href in a REPORT response is absolute on
caldav.icloud.com(36 of 36 in one test). When the client talks to the partition host, the hrefs normally match it. Sometimes, though, a response to the partition host contains hrefs oncaldav.icloud.com. DAVObject.__init__doesclient.url.join(url), andURL.joinraises whenever the hostnames differ.
The two hosts serve the same account, so the href is valid. It just names the other front end.
Minimal reproduction (no network)
from caldav import DAVClient
from caldav.calendarobjectresource import Event
client = DAVClient(url="https://p49-caldav.icloud.com/12345678/calendars/", username="u", password="p")
Event(client, url="https://caldav.icloud.com/12345678/calendars/cal/event.ics")
# ValueError: https://p49-caldav.icloud.com/12345678/calendars/ can't be joined with https://caldav.icloud.com/12345678/calendars/cal/event.ics
The same thing happens with a Calendar whose URL is on the generic host.
Suggested fix
When an href is absolute but on a different host, and both hosts are the same service (for iCloud: both end in .icloud.com, same scheme), join by path onto the client's host instead of raising. Requests then only ever go to the host the client already uses, so no request (and no credential) goes to a new host. Every other host mismatch still raises, which keeps the protection join gives today.
As a local workaround I'm wrapping URL.join like this:
_original_join = URL.join
def _join(self, path):
try:
return _original_join(self, path)
except ValueError:
other = URL.objectify(path)
if other is None:
raise
hosts = (self.hostname or "", other.hostname or "")
if not all(h.endswith(".icloud.com") for h in hosts) \
or (self.scheme or "https") != (other.scheme or "https"):
raise
return _original_join(self, other.path + (f"?{other.query}" if other.query else ""))
A cleaner upstream fix might belong where the "icloud hack" already lives in _post_request_report_build_resultlist, or in the calendar_home_set setter. One option is to remember the original host as an alias of the rewritten one, so hrefs on either host are accepted. I'm happy to turn this into a PR with a test if you tell me which approach you prefer.
Environment
- caldav 3.3.0a1 (Home Assistant 2026.10.0, Python 3.14); same
URL.joinandDAVObject.__init__logic on master b8497e9 - Server: iCloud (
caldav.icloud.com→ partitionp49-caldav.icloud.com)
- Ngôn ngữ chính
- Python
- Star
- 412
- Fork
- 113
- Merge trung bình
- 1 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 26
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của python-caldav/caldav
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
python-caldav/caldav#687 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 52/100
python-caldav/caldav#749 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
python-caldav/caldav#725 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 48/100
python-caldav/caldav#720 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
python-caldav/caldav#704 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của python-caldav/caldav
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
KalicoCrew/kalico#1012 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
esphome/esphome.io#7657 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
VNG-Realisatie/gemma-zaken#2658 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
comp/gateway comp/plugins duplicate P3 type/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
NousResearch/hermes-agent#137019 ·
Maintainer thường phản hồi trong vòng 1 ngày