home-assistant/core · warning · ServiceValidationError

not_a_water_heater_device

not_a_water_heater_device

Error message

The selected device ({device_name}) is not a water heater. Please select the water heater sub-device.

What it means

ServiceValidationError raised by `_ensure_water_heater_device` when the bsblan device passed to `set_hot_water_schedule` is not the water-heater sub-device. The check requires an identifier of the form `{something}-water-heater` in the domain-bsblan identifiers; the main controller device or a circuit device fails it. Translation key `not_a_water_heater_device` names the device.

Source

Thrown at homeassistant/components/bsblan/services.py:178

            translation_domain=DOMAIN,
            translation_key="config_entry_not_loaded",
            translation_placeholders={"device_name": device_entry.name or device_id},
        )

    return entry, device_entry


def _device_name(device_entry: dr.DeviceEntry) -> str:
    """Return the best available display name for a device."""
    return device_entry.name_by_user or device_entry.name or device_entry.id


def _ensure_water_heater_device(device_entry: dr.DeviceEntry) -> None:
    """Validate the service targets the water heater sub-device."""
    for domain, identifier in device_entry.identifiers:
        if domain == DOMAIN and identifier.endswith("-water-heater"):
            return
    raise ServiceValidationError(
        translation_domain=DOMAIN,
        translation_key="not_a_water_heater_device",
        translation_placeholders={"device_name": _device_name(device_entry)},
    )


async def set_hot_water_schedule(service_call: ServiceCall) -> None:
    """Set hot water heating schedule."""
    entry, device_entry = _resolve_config_entry(service_call)
    _ensure_water_heater_device(device_entry)
    client = entry.runtime_data.client

    days = _build_weekly_schedule_days(service_call)
    dhw_schedule = DHWSchedule(**days)

    LOGGER.debug("Setting hot water schedule: %s", dhw_schedule)

    try:

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Select the sub-device literally named/labeled as the water heater (identifier ending in `-water-heater`).
  2. In YAML, confirm the device's identifiers via Developer Tools > Template before hardcoding.
  3. If no water-heater sub-device exists, the boiler has no DHW circuit exposed — this action cannot be used.
Defensive patterns

Strategy: type-guard

Validate before calling

# template: confirm the chosen device is the water heater sub-device
{{ device_attr(device_id, 'identifiers') | select('match', 'bsblan:.*-water-heater$') | list | length > 0 }}

Type guard

def is_water_heater_device(device_entry: dr.DeviceEntry) -> bool:
    return any(
        domain == "bsblan" and identifier.endswith("-water-heater")
        for domain, identifier in device_entry.identifiers
    )

Prevention

When it happens

Trigger: Calling `bsblan.set_hot_water_schedule` with the top-level BSB-LAN controller device (or a heating-circuit device) instead of the dedicated water heater sub-device created for DHW.

Common situations: Users selecting the 'BSB-LAN Controller' device in the picker or in YAML because it is the most prominent one; homes without a DHW circuit where no water-heater sub-device exists at all.

Related errors


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