Repository navigation
feat!: update undici to v8 (Node.js >=22.19), configurable request timeouts - #400
Merged
Merged
Conversation
undici 8 declares engines node >=22.19.0 and fails on import under Node 20 (TypeError: webidl.util.markAsUncloneable is not a function). Node 20 is dropped from engines and the CI matrix; Node 26 is added. Reviewed the undici 8 breaking changes against our usage: the legacy handler wrappers are gone (our interceptors only pass the handler through), non-real Blob bodies are rejected (we never send one), and interceptors.responseError keeps its behaviour. HTTP/2 is now negotiated by default via ALPN. eXist 6 answers with HTTP/1.1, eXist 7 selects h2 on its TLS port; REST and XML-RPC both work over h2, and the suite fails the same tests against 7.0.0-SNAPSHOT with undici 7 and undici 8. BREAKING CHANGE: Node.js >=22.19.0 is required. Closes eXist-db#398, supersedes eXist-db#392 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bdrW9vpnvJkeBtS1UZ92E
undici aborts a request after 300 seconds without response headers or without a body chunk. Long running queries and package installations regularly take longer and failed with UND_ERR_HEADERS_TIMEOUT. - connection option `timeout` (milliseconds, 0 waits indefinitely) sets undici's headersTimeout and bodyTimeout; the default is now 0 - readOptionsFromEnv reads EXISTDB_TIMEOUT - methodCall accepts per-call options; queries.execute, read and readAll and REST post take `timeout` from their options and do not send it to the database - app.upload, install, deploy and remove never time out REST post no longer deletes attribute options from the object passed in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bdrW9vpnvJkeBtS1UZ92E
put and post set content-length to body.length, which counts the characters of a string, not its bytes. Any non-ASCII character made undici reject the request with UND_ERR_REQ_CONTENT_LENGTH_MISMATCH. undici derives content-length from the body itself, in bytes, for strings and buffers alike, so the header is no longer set by hand. Streams were already sent without it; their separate branch in put is gone because it is now identical to the default one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bdrW9vpnvJkeBtS1UZ92E
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| CodeStyle | 8 minor |
🟢 Metrics 34 complexity · 0 duplication
Metric Results Complexity 34 Duplication 0
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
- build the attributes and properties of a REST query from Object.entries instead of looking up and deleting computed keys (security/detect-object-injection, no-dynamic-delete); attributes now follow the order of the options, which XML does not care about - drop the unused `_` parameter in app.upload - no bold text in the new timeout example of the README (MD050) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bdrW9vpnvJkeBtS1UZ92E
This was referenced Sep 11, 2026
joewiz
approved these changes
Sep 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #398, closes #401. Supersedes #392.
Three commits, meant to be merged as they are (not squashed) so semantic-release sees the breaking change, the feature and the fix.
1.
feat!: require Node.js 22.19 and update undici to v8^8.10.2, engines>=22.19.0(not^22.19.0, which would exclude Node 24 and 26)[22, 24, 26], Node 20 droppedTypeError: webidl.util.markAsUncloneable is not a function, see the CI of chore: bump undici from 7.25.0 to 8.5.0 #392), so this is a real breaking changeinterceptors.responseErroris unchanged2.
feat: make request timeouts configurable, wait indefinitely by defaultundici aborts a request after 300 seconds without response headers or without a body chunk, which cut off long running queries and package installations.
timeoutin milliseconds,0waits indefinitely; the default is now0readOptionsFromEnvreadsEXISTDB_TIMEOUTtimeoutin the options ofqueries.execute,read,readAlland RESTpostoverrides the connection timeout and is not sent to the database;methodCall(name, params, { timeout })app.upload,install,deployandremovenever time outpostno longer deletes attribute options from the object passed in3.
fix(rest): send non-ASCII strings with put and postputandpostsetcontent-lengthtobody.length, which counts characters, not bytes. Any non-ASCII string failed withUND_ERR_REQ_CONTENT_LENGTH_MISMATCH, with undici 7 as well. undici derives the header from the body itself, so it is no longer set by hand. Streams were already sent without it.Testing
Locally against
existdb/existdb:6.4.0:New specs:
spec/tests/timeout.js(24 tests) and a non-ASCII block inspec/tests/rest.js(3 tests).Against
existdb/existdb:latest(7.0.0-SNAPSHOT, h2):timeout.js24/24 and the non-ASCII REST tests pass. The full suite fails 7 tests there, identically with undici 7 onmain: eXist 7 behaviour changes (EXPATH007 error message, XML declaration serialized by default, RESTstart/max/cache), see #339.The
releasecells in CI have failed on every PR since June (e.g. #391, #394), independent of this change.Downstream
xst and gulp-exist depend on
^7.0.0and keep working until they opt in. Adopting 8.0.0 requires Node.js >=22.19 there as well.🤖 Generated with Claude Code
https://claude.ai/code/session_016bdrW9vpnvJkeBtS1UZ92E