Skip to content

Possible http2 bug: 'data' event called before 'response' event #52205

Open
@st3ffgv4

Description

@st3ffgv4

Version

v20.11.1

Platform

Microsoft Windows NT 10.0.22631.0 x64

Subsystem

No response

What steps will reproduce the bug?

import { Agent, fetch } from "undici";

const dispatcher = new Agent({ allowH2: true });

(async () => {
  while (true) {
    console.log("fetching 1000 requests");
    console.time();
    await Promise.all(
      Array.from({ length: 1000 }).map(async () => {
        try {
          const response = await fetch("https://http2.pro/api/v1", {
            dispatcher,
          });
          await response.text();
        } catch (e) {
          console.error(e);
        }
      }),
    );
    console.timeEnd();
  }
})();

How often does it reproduce? Is there a required condition?

Sporadically when doing massive http2 requests for a certain period of time a breaking assertion is triggered "assert(!this.aborted)" in onHeaders Method [undici/lib/core/request.js] causing application crash

This probably will affect also native fetch based on undici if used with http2

What is the expected behavior? Why is that the expected behavior?

I expect that response event is emitted before data event

What do you see instead?

assetion error "assert(!this.aborted)" and application crash

node:assert:408
throw err;
^

AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

assert(!this.aborted)

at Request.onHeaders (C:\Users\gava9\OneDrive\Documents\progetti\undici\lib\core\request.js:235:5)
at ClientHttp2Stream.<anonymous> (C:\Users\gava9\OneDrive\Documents\progetti\undici\lib\dispatcher\client-h2.js:394:17)
at Object.onceWrapper (node:events:633:26)
at ClientHttp2Stream.emit (node:events:518:28)
at emit (node:internal/http2/core:331:3)
at process.processTicksAndRejections (node:internal/process/task_queues:85:22) {

generatedMessage: true,
code: 'ERR_ASSERTION',
actual: false,
expected: true,
operator: '=='
}

if i log the exception that is causing request abortion is

TypeError: Cannot read properties of null (reading 'push')
at Object.onData (C:\Users\gava9\OneDrive\Documents\progetti\undici\lib\web\fetch\index.js:2233:28)
at Request.onData (C:\Users\gava9\OneDrive\Documents\progetti\undici\lib\core\request.js:254:29)
at ClientHttp2Stream. (C:\Users\gava9\OneDrive\Documents\progetti\undici\lib\dispatcher\client-h2.js:422:17)
at ClientHttp2Stream.emit (node:events:518:28)
at addChunk (node:internal/streams/readable:559:12)
at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
at Readable.push (node:internal/streams/readable:390:5)
at Http2Stream.onStreamRead (node:internal/stream_base_commons:190:23)

Additional information

I have first opened a pull request directly to undici package nodejs/undici#2985 and they point me to open an issue here before.
The problem is that:
sporadically, after a certain period of time making requests continuosly, happens that the 'data' event of the http2 stream is emitted before 'response' event.
In undici fetch lib or also in native fetch implementation, the body Readable is initiliazed only if headers are sent.
Is this considered a nodejs http2 bug?

Metadata

Metadata

Assignees

No one assigned

    Labels

    http2Issues or PRs related to the http2 subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions