Skip to content

Debounce in service collection throws UnhandledPromiseRejection when connection is terminated in window #533

Open
@zachowj

Description

@zachowj

The 5-second debounce in subscribeServices is causing an UnhandledPromiseRejection. When the Home Assistant connection is terminated during the debounce window, sendMessage is called while the connection is already in a disconnected state, leading to the rejection.

Steps to Reproduce:

  1. Run the provided example script.
  2. Start Home Assistant.
  3. Wait five seconds after disconnect to observe the issue.

This can be easily reproduced by starting the script before Home Assistant is fully up, allowing the service updates to trigger the debounce.

Example Code:

import {
  createConnection,
  subscribeServices,
  createLongLivedTokenAuth,
} from "./dist/index.js";

(async () => {
  const auth = createLongLivedTokenAuth(
    "http://localhost:8123",
    "<TOKEN>",
  );

  let counter = 0;
  const connection = await createConnection({ auth, setupRetry: -1 });
  subscribeServices(connection, () => {
    console.log("Services updated", counter++);
    // wait for 2 updates so debounce fetches services
    // simulate connection close from client
    // this can be removed and manually terminate Home Assistant before the debounce fetches services
    if (counter > 2 && connection.connected) {
      console.log("Closing connection");
      connection.close();
      console.log("wait for it...");
    }
  });
})();

Console Output:

Services updated 0
Services updated 1
Services updated 2
Closing connection
wait for it...
node:internal/process/promises:389
      new UnhandledPromiseRejection(reason);
      ^

UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "3".
    at throwUnhandledRejectionsMode (node:internal/process/promises:389:7)
    at processPromiseRejections (node:internal/process/promises:470:17)
    at process.processTicksAndRejections (node:internal/process/task_queues:96:32) {
  code: 'ERR_UNHANDLED_REJECTION'
}

Stack Trace: line numbers are 2 off due to console.logs i had in the code

sendMessage:  { type: 'get_services' }  connected:  false
Error
    at Connection.sendMessage (file:///home/jason/projects/home-assistant-js-websocket/dist/connection.js:244:21)
    at file:///home/jason/projects/home-assistant-js-websocket/dist/connection.js:283:18
    at new Promise (<anonymous>)
    at Connection.sendMessagePromise (file:///home/jason/projects/home-assistant-js-websocket/dist/connection.js:266:16)
    at getServices (file:///home/jason/projects/home-assistant-js-websocket/dist/commands.js:3:55)
    at fetchServices (file:///home/jason/projects/home-assistant-js-websocket/dist/services.js:31:33)
    at file:///home/jason/projects/home-assistant-js-websocket/dist/services.js:30:58
    at Timeout.later [as _onTimeout] (file:///home/jason/projects/home-assistant-js-websocket/dist/util.js:27:22)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7)

Metadata

Metadata

Assignees

No one assigned

    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