Repository navigation
SubscribeToHomeAssistantEventsAsync never sends the requested event_type #1443
Description
The problem
IHomeAssistantConnection.SubscribeToHomeAssistantEventsAsync(eventType, cancelToken) never places the requested eventType on the outgoing subscribe_events websocket command. Every subscription that goes through the non-cached path is sent with no event_type field at all, so Home Assistant treats it as a subscription to all events.
For a non-admin user token this is fatal: Home Assistant's subscribe_events handler defaults a missing event_type to MATCH_ALL and then rejects the command as unauthorized unless the connecting user is an admin or the resolved type is on a small allow-list. A non-admin client can never obtain a working event subscription through this method, no matter which specific event type it asks for. For an admin token the call still silently over-subscribes to every event instead of the one requested.
Environment
- NetDaemon release with the issue: 26.32.0 (also present on the current
mainbranch — no later fix) - Last working NetDaemon release (if known): unknown; the code path appears unconditional
- Operating environment: any client using
NetDaemon.Client'sIHomeAssistantConnectiondirectly or viaHassModel - Link to integration documentation on our website:
Link to or paste code that causes the issue
SubscribeToHomeAssistantEventsInternalAsync in
src/Client/NetDaemon.HassClient/Internal/HomeAssistantConnection.cs:
private async Task<IObservable<HassEvent>> SubscribeToHomeAssistantEventsInternalAsync(string? eventType,
CancellationToken cancelToken)
{
var combinedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
cancelToken,
_internalCancelSource.Token
);
var result = await SendCommandAndReturnHassMessageResponseAsync(new SubscribeEventCommand(),
combinedTokenSource.Token).ConfigureAwait(false);
...
}The eventType parameter is never read in the method body. SubscribeEventCommand (src/Client/NetDaemon.HassClient/Internal/HomeAssistant/Commands/SubscribeEventCommand.cs) does expose a settable EventType property with [JsonPropertyName("event_type")], but nothing ever assigns it, so it is never serialised.
Minimal reproduction:
await connection.SubscribeToHomeAssistantEventsAsync("state_changed", cancellationToken);using a long-lived access token for a non-admin user.
Expected: the outgoing message is {"type":"subscribe_events","event_type":"state_changed",...} and Home Assistant accepts it, since state_changed is one of the event types a non-admin connection is permitted to subscribe to individually.
Actual: the outgoing message is {"type":"subscribe_events",...} with no event_type field. Home Assistant's handle_subscribe_events (homeassistant/components/websocket_api/commands.py, current main) defaults the missing field to MATCH_ALL and then raises Unauthorized because the connection is not an admin (SUBSCRIBE_ALLOWLIST only covers a fixed set of types, and MATCH_ALL is not one of them). The subscribe call fails outright for a non-admin token.
Traceback/Error logs
Home Assistant's websocket connection returns an unauthorized error result for the subscribe_events command id, and logs Refusing to allow <user> to subscribe to event __ALL__ server-side (event type resolved as MATCH_ALL).
Additional information
Home Assistant's own admin gate (for reference, homeassistant/components/websocket_api/commands.py, current main):
@decorators.websocket_command(
{
vol.Required("type"): "subscribe_events",
vol.Optional("event_type", default=MATCH_ALL): str,
}
)
def handle_subscribe_events(...):
event_type = msg["event_type"]
if event_type not in SUBSCRIBE_ALLOWLIST and not connection.user.is_admin:
raise Unauthorized(user_id=connection.user.id)
A fix that sets EventType = eventType on the constructed SubscribeEventCommand in SubscribeToHomeAssistantEventsInternalAsync addresses this for both non-admin subscriptions and the unnecessary all-events over-subscription for admin users.
Activity
FrankBakkerNl commentedon Sep 25, 2026
I did not think NetDaemon would work at all with a non-admin user token. Did you find most of the other functionality does work?