-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[🐞] Error on response attempting to close WritableStream with Bun adapter #5929
Comments
+1 same behavior here |
@wmertens Do you know if this error is caused by Bun or by Qwik? |
The error occurs in this line of code For some reason, at that line, "writableStream" is in "locked" state, and therefore cannot be closed. |
I'm not sure, but I tried Qwik with Node.js servers and I don't get this error, so it might be. |
Well, open for PRs :) |
If before executing if (!writableStream.locked) {
await writableStream.close();
} |
well if lock is true then it will throw an error correct? unless this error will only throw in bun |
Yes, if |
what about if (writableStream.locked) {
writableStream.releaseLock();
}
await writableStream.close(); |
ChatGPT 😏 suggested this after I asked it to account for every gotcha haha export function renderQwikMiddleware(render: Render) {
return async (requestEv: RequestEvent) => {
// Your existing code...
try {
// Your rendering logic...
} finally {
try {
await stream.ready;
await stream.close();
console.log('Writer closed successfully');
} catch (error) {
console.error('Error closing the writer', error);
}
try {
await pipe;
console.log('pipe operation completed successfully');
} catch (error) {
console.error('Error in pipe operation', error);
if (writableStream.abort) {
writableStream.abort(error);
}
}
if (!writableStream.locked) {
try {
await writableStream.close();
console.log('Stream closed successfully');
} catch (error) {
console.error('Error occurred when closing the writable stream', error);
}
} else {
console.error('The writable stream is locked.');
// Wait 2 seconds
const waitTime = 2000;
await new Promise(resolve => setTimeout(resolve, waitTime));
if (writableStream.locked) {
try {
stream.releaseLock();
console.log('The writer has been released, trying to close the stream again');
await writableStream.close();
} catch (error) {
console.error('Error occurred when forcibly trying to close the writable stream', error);
}
}
}
}
};
} |
In this WritableStream {
locked: true,
abort: [Function: abort],
close: [Function: close],
getWriter: [Function: getWriter],
} |
oh i see ChatGPT got releaseLock from writableStream.getWriter().releaseLock();
console.log('The writer has been released, trying to close the stream again');
await writableStream.close(); |
even if we do this it's weird that it's only bun. maybe something else is wrong. we have another team using bun with no issues |
It does not seem to be a type problem, since I try to execute |
Maybe I'm wrong, but I think they are different. https://developer.mozilla.org/en-US/docs/Web/API/WritableStreamDefaultWriter https://developer.mozilla.org/en-US/docs/Web/API/WritableStream |
The problem is when trying to execute |
Do they use Bun.serve as production server with Qwik? With which version of Bun and Qwik? |
@devcaeg you can access the reference with |
Are you using |
I'm going to download the repro and try it |
yeah it looks like bun doesn't have releaseLock |
I tried 1.1.8 not working. maybe we need to ping bun guys |
I wrote in
|
makes sense |
Let's figure out if the issue occurs because of this polyfill first :) |
Here's the polyfill: qwik/packages/qwik-city/middleware/bun/index.ts Lines 21 to 53 in bb8b7a9
I see from the usage of it that it should return a value, which this polyfill is not doing. |
yeah I asked chatgpt to give me a better polyfil and it works |
the chatgpt version was var TextEncoderStream = class {
constructor() {
this._encoder = new TextEncoder();
this._writer = null;
this.ready = Promise.resolve();
this.reader = null;
this.closed = false;
this.readable = new ReadableStream({
start: controller => {
this.reader = controller;
}
});
this.writable = new WritableStream({
write: async (chunk) => {
if (chunk != null && this.reader) {
let encoded = this._encoder.encode(chunk);
this.reader.enqueue(encoded);
}
},
close: () => {
this.reader.close();
this.closed = true;
},
abort: (reason) => {
this.reader.error(reason);
this.closed = true;
}
});
}
}; |
Yes, it seem to work. |
@octet-stream can you make a pr (you can edit in github directly) and I'll update the pr if needed |
Sure, why not. |
Great! I didn't realize that |
yup i didn't realize either |
I actually did, when I was investigating this problem back March, but I completely forgot to mention it in this issue, sorry. |
here is a pr example #6308 I want you to make a pr so you guys get contributes 😁 |
Here comes the PR :) |
I am satisfied with the simple fact that the error is solved, haha. Thank you both very much. |
@devcaeg @octet-stream |
You mean the polyfill will be exposed from Qwik to be installed manually? This is fine by me, but it must be documented then. |
no I meant for now until the next release. in your codebase look where |
Ah, sure. |
yeah, that way you guys aren't blocked and waiting for the next release 👍 |
Thank you! |
Can confirm this works in my project. Thank you for your help! |
By the way, here's the issue in Bun asking for TextEncoderStrea/TextDecorerStream oven-sh/bun#5648 I'll comment it here to add a reference. There's even a polyfill: oven-sh/bun#5648 (comment) |
oh awesome they had a polyfill |
ok ChatGPT make the encoder version based on the code in that bun issue decoder version add this at the top of your export class _TextEncoderStream_polyfill extends TransformStream<
string,
Uint8Array
> {
encoding: string = "utf-8";
constructor() {
const encoder = new TextEncoder();
super({
transform(
chunk: string,
controller: TransformStreamDefaultController<Uint8Array>
) {
const encoded = encoder.encode(chunk);
if (encoded.byteLength > 0) {
controller.enqueue(encoded);
}
},
flush() {
// When the stream is finished, we don't have any cleanup to do.
// We don't need to enqueue any data because TextEncoder.encode doesn't have any state.
},
});
}
}
globalThis.TextEncoderStream =
globalThis.TextEncoderStream ||
class TextEncoderStream extends _TextEncoderStream_polyfill {}; |
I think the latter is better. Anyway, the best thing is for |
In the latest versions of |
Thanks for the update |
Which component is affected?
Qwik City (routing)
Describe the bug
When using Qwik with Bun adapter (Bun.serve) with disabled SSG, the server throws an error attempting to close locked
WritableStream
. From what I can tell, the stream becomes locked after thepipeTo
call here and it stays on that stage whenwritebleStream.close()
is called here. The server itself however responds without any issue, this error for some reason just shows up in logs, but I get this during every server response response.Reproduction
https://github.com/octet-stream/qwik-bun-stream-issue
Steps to reproduce
bun i
;bun run build
;bun run serve
;After the main page shows up, look at the terminal and you'll see following error:
System Info
Additional Information
No response
The text was updated successfully, but these errors were encountered: