Skip to content

stream/iter: pull() swallows abort when async transform flush resolves to null #65345

Description

@trivikr

Version

main

Platform

N/A

Subsystem

stream

What steps will reproduce the bug?

import { pull, text } from 'node:stream/iter';

const controller = new AbortController();
const reason = new Error('boom');

const transform = async (chunks) => {
  if (chunks !== null) return chunks;

  controller.abort(reason);
  return null;
};

text(pull('x', transform, { signal: controller.signal })).then(
  (value) => console.log('fulfilled:', JSON.stringify(value)),
  (error) => console.log('rejected:', error === reason, error),
);

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

Always

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

rejected: true Error: boom

The pipeline should reject with reason, making error === reason true. An abort during transform flushing should not be converted into normal iterator completion.

From §9.1, Stream.pull(), steps 5–7:

If signal is not undefined, set pipelineController’s signal to follow signal.

What do you see instead?

fulfilled: "x"

The pipeline fulfills successfully with "x", even though its signal was aborted while the asynchronous flush was completing. The abort reason is never delivered to the consumer.

Additional information

No response

Metadata

Metadata

Assignees

Labels

streamIssues and PRs related to the stream subsystem.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions