[solved] CalDAV and the recursion error (aka no calendar is displayed) Is the Caldav Modul to old (1.2.0)

Hi everybody,

I have spent a lot of time over the last few weeks investigating the problem with the recursion error, which occurs quite frequently. Further down then my own programming tests and analyses with Powershell and Python, also the Errorfiles.

RecursionError: maximum recursion depth exceeded

Problem:

No caldav calendar is displayed. There are a lot of errors in logging (see bleow).
In my case I want to integrate a Synology calendar, which runs without problems with DavX on Android and ‘CalDAV Synchonizer’ on Windows 11 and 10.
To exclude problematic entries, a new user and completely new and empty calendar with only 2 entries and simple text was created.

It is unfortunately very difficult as a newbie to find his way around, what are old and outdated example configurations, what is still correct or what is new and to be considered.
Of course the #1 place to go is this one: CalDAV - Home Assistant
But since it doesn’t work, you search a lot on the internet.

Tested under

Home Assistant 10.4 and 10.5.
2023.8.0, 2023.8.1, 2023.8.2

Preliminary:

I have questions of understanding for the configuration, which are not clearly described for me.

configuration.yaml:

  1. does the user and password have to be in “” or not?
  2. is a http://ip/caldav… allowed or must it be a https:// connection?
  3. in many examples either ‘no calendar at all’, “calenders:” or “custom_calendars:” is specified as filter or selection.

Examples:

a.

calendar:
  - platform: caldav
    username: my_username
    password: my_pwd
    url: http://192.168.1.123:5000/caldav/my_user

b.

calendar:
  - platform: caldav
    username: my_username
    password: my_pwd
    url: http://192.168.1.123:5000/caldav/my_user
    calendars:
      - "Family"

c.

calendar:
  - platform: caldav
    username: my_username
    password: my_pwd
    url: http://192.168.1.123:5000/caldav/my_user
    custom_calendars:
      - name: "Family"
        calendar: "Family"
        search: "Family"

=> What is correct?

  1. what kind of restart do I need to do? Is
  • any restart of ‘only one yaml file’ sufficient here when adjusting the configuration?
  • Or a ‘quick start’ or
  • must HA be completely restarted?

My research:

I have tried just about every possibility - so really in every combination.

  • Name and password with and without “”
  • All kinds of restarts
  • url: http://192.168.1.123:5000/caldav/my_user or url: http://192.168.1.123:5000/caldav.php/my_user
  • url: http://192.168.1.123:5000/caldav/ or url: http://192.168.1.123:5000/caldav.php/
  • url: http://192.168.1.123:5000/caldav/my_user/home

After all this did not work, I made my own test query with powershell.
:smiley: : The result was flawless. I was able to make a PROPFIND query and read all the data.

Then I took a closer look at the original HA Python scripts and the error message.

*CalDAV integration fails with RecursionError*

The user has a problem with CalDAV integration in Home Assistant. When trying to add a CalDAV calendar, a RecursionError occurs. The error occurs when Home Assistant tries to connect to the CalDAV server.

The file uses the caldav Python library to interact with CalDAV servers. This is made clear by the import caldav.
The connection to the CalDAV server is established with the following code:

client = caldav.DAVClient(url, None, username, password)
principal = client.principal()
calendars = principal.calendars()

Querying events from the calendar is done with the following code:
results = calendar.date_search(start_date, end_date)

:smiley: I reprogrammed this - and what can I say: everything works fine - in my test environment. :frowning_face:

Further in the logging and the displayed errors:

Error while setting up caldav platform for calendar
File “/usr/src/homeassistant/homeassistant/components/caldav/calendar.py”, line 87, in setup_platform
calendars = client.principal().calendars()

Based on this error message and the contents of the calendar.py file on GitHub, I can determine:

    The error occurs in the setup_platform function of the calendar.py file.
    More specifically, the error occurs when trying to call the calendars() method 
    of the principal object.

The relevant code snippet from the calendar.py file is:

client = caldav.DAVClient(url, None, username, password)
principal = client.principal()
calendars = principal.calendars()

The problem seems to occur when communicating with the CalDAV server via the caldav library, specifically when retrieving the calendar information of the principal object.

The error message further indicates that there is a recursive query that exceeds the maximum recursion depth. This suggests that there may be a problem with the caldav library itself or with the way Home Assistant uses it.

This appears to me to be indicated by the error:

File “/usr/local/lib/python3.11/site-packages/caldav/davclient.py”, line 654, in request
return self.request(url, method, body, headers)

So, why does it work in my rebuilt test in Python and Caldav and not in HA?
The only difference I can see right away is the version of Caldav. Newly installed I use the version 1.3.6. In HA unfortunately the quite old version 1.2.0 is still used. At least that’s how it seems to me:

➜ ~ docker exec -it homeassistant /bin/bash
homeassistant:/config# pip show caldav
Name: caldav
Version: 1.2.0
Summary: CalDAV (RFC4791) client library
Home-page: https://github.com/python-caldav/caldav
Author: Cyril Robert
Author-email: [email protected]
License: GPL
Location: /usr/local/lib/python3.11/site-packages
Requires: icalendar, lxml, pytz, recurring-ical-events, requests, tzlocal, vobject
Required-by:
homeassistant:/config#

I have then also displayed the calendars in my Python query - that all works fine. Only HA refuses to work at all.

I am not fit in how I can update the HA Docker container permanently with Caldav 1.3.6.

Sure I have a
pip install caldav --upgrade

tried. But yes a service restart is probably needed - and bang, 1.2.0 of Caldav is available again.
I don’t know enough about how to get a permanent update for Caldav in this Docker.

Unfortunately, I can’t be sure if it’s really just that.

I’m also not sure if I’m using the right debug mode here. Maybe there would be more info to see where it really hangs.

In config.yaml I entered this, but I’m not sure wqelcher dein or entity is correct here:

logger:
  default: info
  logs:
    homeassistant.components.calendar: critical
    calendar.caldav: critical

What can I do now? Any suggestions?

Regards
Mike

For a better overview in a separated Thread the Errorfile:

first Error

  Logger: homeassistant.components.calendar
  Source: runner.py:179
  Integration: Kalender (documentation, issues)
  First occurred: 18:17:17 (1 occurrences)
  Last logged: 18:17:17
  
  Setup of calendar platform caldav is taking over 10 seconds.

second Error

  
  Logger: homeassistant.components.calendar
  Source: components/caldav/calendar.py:87
  Integration: Kalender (documentation, issues)
  First occurred: 18:09:02 (1 occurrences)
  Last logged: 18:09:02
  
  Error while setting up caldav platform for calendar
  Traceback (most recent call last):
    File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 362, in _async_setup_platform
      await asyncio.shield(task)
    File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
      result = self.fn(*self.args, **self.kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/src/homeassistant/homeassistant/components/caldav/calendar.py", line 87, in setup_platform
      calendars = client.principal().calendars()
                  ^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 411, in principal
      self._principal = Principal(client=self, *largs, **kwargs)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/objects.py", line 480, in __init__
      cup = self.get_property(dav.CurrentUserPrincipal())
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/objects.py", line 210, in get_property
      foo = self.get_properties([prop], **passthrough)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/objects.py", line 235, in get_properties
      response = self._query_properties(props, depth)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/objects.py", line 171, in _query_properties
      return self._query(root, depth)
             ^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/objects.py", line 196, in _query
      ret = getattr(self.client, query_method)(url, body, depth)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   calendar.caldav
      return self.request(url or self.url, "PROPFIND", props, {"Depth": str(depth)})
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 629, in request
      return self.request(url, method, body, headers)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 654, in request
      return self.request(url, method, body, headers)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 654, in request
      return self.request(url, method, body, headers)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 654, in request
      return self.request(url, method, body, headers)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    [Previous line repeated 962 more times]
    File "/usr/local/lib/python3.11/site-packages/caldav/davclient.py", line 582, in request
      r = self.session.request(
          ^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/requests/sessions.py", line 589, in request
      resp = self.send(prep, **send_kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/requests/sessions.py", line 703, in send
      r = adapter.send(request, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/requests/adapters.py", line 486, in send
      resp = conn.urlopen(
             ^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 714, in urlopen
      httplib_response = self._make_request(
                         ^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 466, in _make_request
      six.raise_from(e, None)
    File "<string ", line 3, in raise_from
    File "/usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py", line 461, in _make_request
      httplib_response = conn.getresponse()
                         ^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/http/client.py", line 1378, in getresponse
      response.begin()
    File "/usr/local/lib/python3.11/http/client.py", line 337, in begin
      self.headers = self.msg = parse_headers(self.fp)
                                ^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/http/client.py", line 236, in parse_headers
      return email.parser.Parser(_class=_class).parsestr(hstring)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/parser.py", line 67, in parsestr
      return self.parse(StringIO(text), headersonly=headersonly)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/parser.py", line 56, in parse
      feedparser.feed(data)
    File "/usr/local/lib/python3.11/email/feedparser.py", line 176, in feed
      self._call_parse()
    File "/usr/local/lib/python3.11/email/feedparser.py", line 180, in _call_parse
      self._parse()
    File "/usr/local/lib/python3.11/email/feedparser.py", line 295, in _parsegen
      if self._cur.get_content_maintype() == 'message':
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/message.py", line 621, in get_content_maintype
      ctype = self.get_content_type()
              ^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/message.py", line 605, in get_content_type
      value = self.get('content-type', missing)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/message.py", line 498, in get
      return self.policy.header_fetch_parse(k, v)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/_policybase.py", line 316, in header_fetch_parse
      return self._sanitize_header(name, value)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/usr/local/lib/python3.11/email/_policybase.py", line 287, in _sanitize_header
      if _has_surrogates(value):
         ^^^^^^^^^^^^^^^^^^^^^^
  RecursionError: maximum recursion depth exceeded

And here my Tests and Outputs with my Python Skript and CALDAV Modul 1.3.6

url = http://192.168.1.204:5000/caldav.php/my_user

and tested with http://192.168.1.204:5000/caldav/my_user

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
 <response>
  <href>/caldav.php/my_user/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <principal/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/my_user/home/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <C:calendar/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/my_user/.in/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <C:schedule-inbox/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/my_user/home_todo/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <C:calendar/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
</multistatus>

url = http://192.168.1.204:5000/caldav.php/

and tested http://192.168.1.204:5000/caldav/

<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:">
 <response>
  <href>/caldav.php/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/group%3D%3Dusers/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <principal/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
 <response>
  <href>/caldav.php/Ela/</href>
  <propstat>
   <prop>
    <resourcetype>
     <collection/>
     <principal/>
    </resourcetype>
   </prop>
   <status>HTTP/1.1 200 OK</status>
  </propstat>
 </response>
</multistatus>

Is this perhaps the wrong place in the forum, should I rather put this in Github?
But then where exactly please?

After some Updates from Home Assistant it is suddenly working.