Skip to content

consumePush crashes when chunk arrives after body.json() teardown #5356

@akaNightmare

Description

@akaNightmare

Bug Description

Calling body.json() (or other consume helpers) and then tearing down the stream (abort/timeout/close) runs consumeFinish(), which sets consume.body = null. stream[kConsume] is left in place.
If BodyReadable.push() runs after that - for example a late chunk from the decompress interceptor- it still calls consumePush(), which does consume.body.push(chunk) and throws:

TypeError: Cannot read properties of null (reading 'push')
    at consumePush (lib/api/readable.js:549)

This is a synchronous throw, not the AbortError from the .json() promise.

Reproducible By

const { Readable: BodyReadable } = require('undici/lib/api/readable');

describe('undici BodyReadable consume race', () => {
    it('must throw when a chunk arrives after consume teardown', async () => {
        const body = new BodyReadable({ resume: () => {}, abort: () => {} });
        const jsonPromise = body.json();

        await new Promise(resolve => queueMicrotask(resolve));

        body.emit('close');

        expect(() => body.push(Buffer.from('late chunk'))).toThrow(/Cannot read properties of null \(reading 'push'\)/);

        await expect(jsonPromise).rejects.toMatchObject({ name: 'AbortError' });
    });
});

in real usage: request() + interceptors.decompress(), body.json() with a short AbortSignal timeout while the response is still streaming

Expected Behavior

Late chunks after consume teardown should be dropped. .json() should reject with AbortError only - no extra sync crash.

Logs & Screenshots

TypeError: Cannot read properties of null (reading 'push')
    at consumePush (/.../undici/lib/api/readable.js:549:16)
    at BodyReadable.push (/.../undici/lib/api/readable.js:160:9)

Environment

  • undici 7.27.0
  • Node.js v24.12.0
  • macOS / Linux, HTTP/1.1
  • Agent.compose(interceptors.decompress())

Additional context

Looks related to #4880 (null guard for late push after H2 teardown). consumePush has no similar guard.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions