Skip to content

SubscribeToHomeAssistantEventsAsync never sends the requested event_type #1443

Closed

Description

@ezpl

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 main branch — no later fix)
  • Last working NetDaemon release (if known): unknown; the code path appears unconditional
  • Operating environment: any client using NetDaemon.Client's IHomeAssistantConnection directly or via HassModel
  • 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

  1. FrankBakkerNl commented on Sep 25, 2026

    @FrankBakkerNl
    Contributor

    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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions