home-assistant/core · error · HomeAssistantError

Failed to validate CalendarEvent: {err}

Error message

Failed to validate CalendarEvent: {err}

What it means

HomeAssistantError raised in CalendarEvent.__post_init__ when the dataclass fails CALENDAR_EVENT_SCHEMA validation (voluptuous). Any integration constructing a CalendarEvent with invalid content — bad summary type, invalid start/end types, malformed recurrence rule — trips this during object construction.

Source

Thrown at homeassistant/components/calendar/__init__.py:414

        return not isinstance(self.start, datetime.datetime)

    def as_dict(self) -> dict[str, Any]:
        """Return a dict representation of the event."""
        return {
            **dataclasses.asdict(self, dict_factory=_event_dict_factory),
            "all_day": self.all_day,
        }

    def __post_init__(self) -> None:
        """Perform validation on the CalendarEvent."""

        def skip_none(obj: Iterable[tuple[str, Any]]) -> dict[str, str]:
            return {k: v for k, v in obj if v is not None}

        try:
            CALENDAR_EVENT_SCHEMA(dataclasses.asdict(self, dict_factory=skip_none))
        except vol.Invalid as err:
            raise HomeAssistantError(
                f"Failed to validate CalendarEvent: {err}"
            ) from err

        # It is common to set a start an end date to be the same thing for
        # an all day event, but that is not a valid duration. Fix to have a
        # duration of one day.
        if (
            not isinstance(self.start, datetime.datetime)
            and not isinstance(self.end, datetime.datetime)
            and self.start == self.end
        ):
            self.end = self.start + datetime.timedelta(days=1)


def _event_dict_factory(obj: Iterable[tuple[str, Any]]) -> dict[str, str]:
    """Convert CalendarEvent dataclass items to dictionary of attributes."""
    result: dict[str, str] = {}
    for name, value in obj:

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Inspect the values passed to CalendarEvent just before construction (log start/end/summary types)
  2. Coerce types before construction: parse datetimes with dt_util, ensure summary/description are str or None
  3. If writing a custom integration, validate upstream data against your own mapping before creating CalendarEvent

Example fix

# before
event = CalendarEvent(
    summary=event_data["title"],  # may be None or dict from a flaky API
    start=event_data["start"],  # raw string, not parsed
    end=event_data["end"],
)

# after
from homeassistant.util import dt as dt_util

summary = str(event_data["title"]) if event_data.get("title") else ""
event = CalendarEvent(
    summary=summary,
    start=dt_util.parse_datetime(event_data["start"]),
    end=dt_util.parse_datetime(event_data["end"]),
)
Defensive patterns

Strategy: validation

Validate before calling

from homeassistant.util import dt as dt_util

# Coerce before constructing CalendarEvent
summary = str(raw["title"]) if raw.get("title") else ""
start = dt_util.parse_datetime(raw["start"]) or dt_util.parse_date(raw["start"])
end = dt_util.parse_datetime(raw["end"]) or dt_util.parse_date(raw["end"])
assert start is not None and end is not None

Type guard

from datetime import date, datetime

def is_valid_calendar_event_fields(
    summary: object, start: object, end: object
) -> bool:
    return (
        summary is None or isinstance(summary, str)
    ) and (
        isinstance(start, (datetime, date))
        and isinstance(end, (datetime, date))
        and (isinstance(start, datetime) == isinstance(end, datetime))
    )

Try / catch

try:
    CalendarEvent(summary=summary, start=start, end=end)
except HomeAssistantError as err:
    logger.error("Rejected upstream event data: %s", err)
    # skip or sanitize the record instead of failing the whole platform

Prevention

When it happens

Trigger: A calendar platform integration (or a caller building CalendarEvent directly) passes fields that violate the schema: non-string summary/description, invalid datetime vs date mixing, or a bad rrule string. __post_init__ serializes the dataclass (skipping Nones) and runs it through the voluptuous schema.

Common situations: Custom calendar integrations mapping third-party API data with unexpected types or None handling, upstream APIs changing field formats, or local calendar YAML/webhook data inserted without sanitization.

Related errors


AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14). Data as JSON: /api/errors/464f9d67856dde8a. Report an issue: GitHub.