Repository navigation
Closed
Labels
H2Pull requests or issues related to HTTP/2Pull requests or issues related to HTTP/2bugSomething isn't workingSomething isn't working
Description
Bug Description
As the title, pipelined requests might fail unexpectedly if another request toward the same domain has been aborted:
node:assert:399
throw err;
^
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert(!this.aborted)
at Request.onHeaders (/home/runner/undici-h2-promise-any/node_modules/undici/lib/core/request.js:235:5)
at ClientHttp2Stream.<anonymous> (/home/runner/undici-h2-promise-any/node_modules/undici/lib/client.js:1804:17)
at Object.onceWrapper (node:events:628:26)
at ClientHttp2Stream.emit (node:events:513:28)
at emit (node:internal/http2/core:330:3)
at process.processTicksAndRejections (node:internal/process/task_queues:85:22) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
Node.js v18.16.1
Reproducible By
https://replit.com/@isukkaw/undici-h2-promise-any
const undici = require('undici');
undici.setGlobalDispatcher(new undici.Agent({
allowH2: true,
pipelining: 10
}));
const { fetch } = undici;
const fetchUbuntuXenialReleaseGpg = () => {
const controller = new AbortController();
return Promise.any(
[
'https://mirror-cdn.xtom.com/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.com/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.com.hk/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.de/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.nl/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.ee/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.jp/ubuntu/dists/xenial/Release.gpg',
'https://mirrors.xtom.au/ubuntu/dists/xenial/Release.gpg'
].map(async url => {
try {
const resp = await fetch(url, { signal: controller.signal });
const text = await resp.text();
// The body should have been consumed, abort the requests
controller.abort();
return text;
} catch(e) {
if (e.name !== 'AbortError') {
console.error('Request Fail:', url)
throw e;
}
}
})
);
};
const fetchDebianBookwormReleaseGpg = () => {
const controller = new AbortController();
return Promise.any(
[
'https://mirror-cdn.xtom.com/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.com/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.com.hk/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.de/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.nl/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.ee/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.jp/debian/dists/bookworm/Release.gpg',
'https://mirrors.xtom.au/debian/dists/bookworm/Release.gpg'
].map(async url => {
try {
const resp = await fetch(url, { signal: controller.signal });
const text = await resp.text();
// The body should have been consumed, abort the requests
controller.abort();
return text;
} catch(e) {
if (e.name !== 'AbortError') {
console.error('Request Fail:', url)
throw e;
}
}
})
);
};
(async () => {
const [ubuntu, debian] = await Promise.all([
fetchUbuntuXenialReleaseGpg(),
fetchDebianBookwormReleaseGpg()
]);
console.log({
ubuntu: ubuntu.length,
debian: debian.length
})
})();Expected Behavior
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: assert(!this.aborted) should never happened.
Logs & Screenshots
(node:3251) [UNDICI-H2] Warning: H2 support is experimental, expect them to change at any time.
(Use `node --trace-warnings ...` to show where the warning was created)
node:assert:399
throw err;
^
AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert(!this.aborted)
at Request.onHeaders (/home/runner/undici-h2-promise-any/node_modules/undici/lib/core/request.js:235:5)
at ClientHttp2Stream.<anonymous> (/home/runner/undici-h2-promise-any/node_modules/undici/lib/client.js:1804:17)
at Object.onceWrapper (node:events:628:26)
at ClientHttp2Stream.emit (node:events:513:28)
at emit (node:internal/http2/core:330:3)
at process.processTicksAndRejections (node:internal/process/task_queues:85:22) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}
Node.js v18.16.1
Environment
Node.js 18.16.0 on Ubuntu 22.04.1
Metadata
Metadata
Assignees
Labels
H2Pull requests or issues related to HTTP/2Pull requests or issues related to HTTP/2bugSomething isn't workingSomething isn't working
Activity
KhafraDev commentedon Oct 22, 2023
@metcoder95
metcoder95 commentedon Oct 22, 2023
Started doing some research about, and bug is in fact quite complex; it seems that somewhere we are reusing a
requestinstance that was already aborted to handle a second request. Haven't found the root cause yet. I'll made more research later onjackschu commentedon Oct 25, 2023
The repro SukkaW provided still reproduces even with Pipelining disabled, maybe this issue should be re-titled?
Trying to swap to undici in our software, I'm able to get this stack trace, we only issue one request to a dummy /debug/stream endpoint which pushes one sse per second and abort it after a few seconds.
but we receive exactly one more chunk afterwards, resulting in this assertion failure
[-][HTTP/2] Pipelined requests might fail unexpectedly if another request toward the same domain has been aborted[/-][+][HTTP/2] Aborted requests for same dome might fail unexpectedly[/+][-][HTTP/2] Aborted requests for same dome might fail unexpectedly[/-][+][HTTP/2] Aborted requests for same domain might fail unexpectedly[/+]fix(#2364): concurrent aborts (#3005)
fix(#2364): concurrent aborts (#3005)
fix(#2364): concurrent aborts (#3005)
test(http2-abort): swallow post-test ECONNRESET on concurrent aborts
fix(h2): make Client multiplex on h2 (#4143) (#5362)