withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
45.61k stars 2.39k forks source link

There was an uncaught error in the middle of the stream while rendering (TypeError: iterator.return is not a function) #10301

Closed xriter closed 6 months ago

xriter commented 6 months ago

Astro Info

Astro                    v4.4.8
Node                     v18.17.1
System                   macOS (arm64)
Package Manager          npm
Output                   server
Adapter                  @astrojs/node
Integrations             @astrojs/tailwind
                         @astrojs/react

Describe the Bug

The problem as described below, was first mentioned in #10184, but seems to be still an issue.

The following error is being logged sometimes:

There was an uncaught error in the middle of the stream while rendering /. TypeError: iterator.return is not a function
    at Object.cancel (node:internal/deps/undici/undici:666:34)
    at readableStreamDefaultControllerCancelSteps (node:internal/webstreams/readablestream:2281:39)
    at [kCancel] (node:internal/webstreams/readablestream:1057:12)
    at ensureIsPromise (node:internal/webstreams/util:192:19)
    at readableStreamCancel (node:internal/webstreams/readablestream:1882:5)
    at readableStreamReaderGenericCancel (node:internal/webstreams/readablestream:2022:10)
    at ReadableStreamDefaultReader.cancel (node:internal/webstreams/readablestream:880:12)
    at ServerResponse.<anonymous> (file:///app/dist/server/entry.mjs:1934:16)
    at ServerResponse.emit (node:events:517:28)
    at emitCloseNT (node:_http_server:1020:10)
// dist/server/entry.mjs (lines: 1922-1947)

 static async writeResponse(source, destination) {
    const { status, headers, body } = source;
    destination.writeHead(status, createOutgoingHttpHeaders(headers));
    if (!body)
      return destination.end();
    try {
      const reader = body.getReader();
      destination.on("close", () => {
        reader.cancel().catch((err) => {
          console.error(
            `There was an uncaught error in the middle of the stream while rendering ${destination.req.url}.`,
            err
          );
        });
      });
      let result = await reader.read();
      while (!result.done) {
        destination.write(result.value);
        result = await reader.read();
      }
      destination.end();
    } catch {
      destination.end("Internal server error");
    }
  }
}

I have not been able to reproduce it consistently yet. The stack trace doesn't point to any custom code, so it seems like it is a problem in the node code?

What is the TypeError: iterator.return is not a function it is referring to?

Anyone else experiencing this?

Could be related to #9614 Supposedly fixed by #10197 - but the error is still thrown for unknown reasons.

lilnasy commented 6 months ago

I'm not sure why the previous issue was closed, the linked PR only affects logging. As for the bug itself, I can't reproduce the it but the issue is clearly with nodejs/undici - it assumes the iterator will always have a return() function, whereas it is supposed to be optional in the iterator protocol.

Considering undici is on v6 but embedded within node 18, 20, and 21 is v5, an upstream PR won't help. We probably have to do a workaround. I'm guessing a no-op return() will do.