Skip to content

Silent Failure on Corrupted XML from Director #35

@deltamikeromeo

Description

@deltamikeromeo

Hi @lawtancool,

First off, thanks for creating this library! I'm using it via your hass-control4 integration. It looks like the library doesn't handle corrupted XML from the director, which makes it tough to debug.

My Situation
My Home Assistant instance was failing to set up the integration, and I kept getting this traceback. After a lot of digging, it turns out my Control4 Director was sending back malformed XML.

2025-07-25 20:16:19.280 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry control4_hc800_000FFF580817 for control4
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 749, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/control4/__init__.py", line 123, in async_setup_entry
    await entry_data[CONF_DIRECTOR].getUiConfiguration()
  File "/usr/local/lib/python3.13/site-packages/pyControl4/director.py", line 303, in getUiConfiguration
    return await self.sendGetRequest("/api/v1/agents/ui_configuration")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/pyControl4/director.py", line 64, in sendGetRequest
    await checkResponseForError(await resp.text())
  File "/usr/local/lib/python3.13/site-packages/pyControl4/error_handling.py", line 98, in checkResponseForError
    dictionary = xmltodict.parse(response_text)
  File "/usr/local/lib/python3.13/site-packages/xmltodict.py", line 359, in parse
    parser.Parse(xml_input, True)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
xml.parsers.expat.ExpatError: mismatched tag: line 6, column 2

The Problem
In pyControl4/error_handling.py, the checkResponseForError function uses a broad try...except that catches the ExpatError but then just ignores it. This makes the library think everything is fine, when really the controller sent broken data.

A Possible Fix?
Maybe the error handling could be a bit more specific? Instead of catching every exception, it could specifically look for the ExpatError and raise a custom error. That would make it much clearer that the problem is coming from the controller's side.

Something like this might work:

# In pyControl4/error_handling.py
from xml.parsers.expat import ExpatError

# ...

def checkResponseForError(response_text):
    try:
        dictionary = xmltodict.parse(response_text)
    except ExpatError as e:
        # This would make it super clear that the controller sent bad XML
        raise C4CorruptXMLResponse(f"Controller sent malformed XML: {e}") from e
    except Exception:
        # Keep this for other non-XML cases
        return

This would have saved me a ton of time troubleshooting!

Thanks for looking into this!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions