Skip to content

readResponseWithSizeLimit can replace streamed size-limit errors with cancellation errors #18571

Description

@teamleaderleo

Description

readResponseWithSizeLimit() can correctly detect that a streamed response exceeded maxBytes, then replace that DownloadError if reader cleanup fails.

The streamed path currently ends with:

finally {
  try {
    await reader.cancel();
  } finally {
    reader.releaseLock();
  }
}

The adjacent cancelResponseBody() helper already ignores cancellation failures to preserve the original rejection, including on the Content-Length size-limit path.

Reproduction

Against current main at ff0f708e917e3f556f889ed9158b396a17f3828c, a native ReadableStream can reproduce the issue:

const cancelError = new Error('cancel failed');

const body = new ReadableStream<Uint8Array>({
  start(controller) {
    controller.enqueue(new Uint8Array([1, 2]));
  },
  cancel() {
    return Promise.reject(cancelError);
  },
});

const response = {
  headers: new Headers(),
  body,
} as Response;

await readResponseWithSizeLimit({
  response,
  url: 'https://example.com/file',
  maxBytes: 1,
});

The two-byte chunk exceeds the one-byte limit, so the operation should fail with a DownloadError.

Current result:

Error: cancel failed

Expected result:

DownloadError: Download of https://example.com/file exceeded maximum size of 1 bytes.

Expected behavior

Cancellation should still be attempted and the reader lock released, but a cancellation failure shouldn't replace the DownloadError that triggered cleanup.

AI SDK Version

ai: 7.0.56

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions