Skip to content

[node] Upgrade undici and remove ErrorRecordingDispatcher for websockets#652

Merged
rkistner merged 3 commits into
mainfrom
undici-errors
Jul 2, 2025
Merged

[node] Upgrade undici and remove ErrorRecordingDispatcher for websockets#652
rkistner merged 3 commits into
mainfrom
undici-errors

Conversation

@rkistner

@rkistner rkistner commented Jul 2, 2025

Copy link
Copy Markdown
Contributor

In earlier versions, undici did not include the underlying cause of errors on websocket connection failures, instead just giving a generic Received network error or non-101 status code., making debugging difficult. This includes connection failures, TLS failures, proxy errors, etc. As a workaround, we used a custom Dispatcher to record the underlying errors.

In v7.11.0, this was fixed by adding the cause property. This PR now removes the custom Dispatcher and just relies on the upstream directly.

Note that this does change the error reported, and you have to use error.cause[.cause] to get to the underlying issue.

Sample error (502 on a proxy) with this change:

[PowerSyncStream] Error: Received network error or non-101 status code.
    at #onFail (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/websocket.js:469:16)
    at Object.onFail (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/websocket.js:63:50)
    at failWebsocketConnection (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/connection.js:319:11)
    at Object.processResponse (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/connection.js:108:9)
    at /home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:1072:19
    at node:internal/process/task_queues:140:7
    at AsyncResource.runInAsyncScope (node:async_hooks:206:9)
    at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  [cause]: DOMException [Error]: Request was cancelled.
      at new DOMException (node:internal/per_context/domexception:53:5)
      at makeAppropriateNetworkError (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/response.js:484:38)
      at httpNetworkFetch (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:1877:14)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
      at async httpNetworkOrCacheFetch (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:1562:29)
      at async httpFetch (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:1133:33)
      at async mainFetch (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:590:18) {
    cause: RequestAbortedError [AbortError]: Proxy response (502) !== 200 when HTTP Tunneling
        at Client.connect (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/dispatcher/proxy-agent.js:154:22)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
      code: 'UND_ERR_ABORTED'
    }
  }
}

Before, with ErrorRecordingDispatcher:

[PowerSyncStream] RequestAbortedError [AbortError]: Proxy response (502) !== 200 when HTTP Tunneling
    at Client.connect (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/dispatcher/proxy-agent.js:153:22)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  code: 'UND_ERR_ABORTED'

Before, without ErrorRecordingDispatcher:

[PowerSyncStream] Error: Received network error or non-101 status code.
    at #onFail (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/websocket.js:469:16)
    at Object.onFail (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/websocket.js:63:43)
    at failWebsocketConnection (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/connection.js:318:11)
    at Object.processResponse (/home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/websocket/connection.js:108:9)
    at /home/ralf/src/powersync-js/packages/node/node_modules/undici/lib/web/fetch/index.js:1072:19
    at node:internal/process/task_queues:140:7
    at AsyncResource.runInAsyncScope (node:async_hooks:206:9)
    at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

@rkistner rkistner requested a review from stevensJourney July 2, 2025 11:13
@changeset-bot

changeset-bot Bot commented Jul 2, 2025

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 335b04d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@powersync/node Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@stevensJourney stevensJourney left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

@rkistner rkistner merged commit 31e942f into main Jul 2, 2025
9 checks passed
@rkistner rkistner deleted the undici-errors branch July 2, 2025 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants