deno: Process exits even when catching: Uncaught (in promise) Http: connection closed before message completed
deno 1.12.2 (release, x86_64-apple-darwin) v8 9.2.230.14 typescript 4.3.5
Refreshing the browser quickly multiple times against a simple local http server can produce a situation where a promise is rejected that cannot be caught, and causes process exits. This is not good when trying to write a stable http server.
for await (const { request, respondWith } of httpConn) {
try {
const res = await computeResponse();
await respondWith(res)
} catch (e) {
console.error('Error in respondWith', e);
}
}
yields:
Error in respondWith Http: connection closed before message completed
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async respondWith (deno:extensions/http/01_http.js:183:27)
at async handle (file:///myfile.ts:87:13)
Http: connection closed before message completed
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async respondWith (deno:extensions/http/01_http.js:183:27)
at async handle (file:///myfile.ts:87:13)
error: Uncaught (in promise) Http: connection closed before message completed
await respondWith(res);
^
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async respondWith (deno:extensions/http/01_http.js:183:27)
at async handle (file:///myfile.ts:87:13)
<process exit>
Tried a .catch(), now none of my code appears in this stacktrace at all!
for await (const { request, respondWith } of httpConn) {
const res = await computeResponse();
respondWith(res).catch(e => console.log(`Error in respondWith`, e));
}
yields:
Http: connection closed before message completed
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async respondWith (deno:extensions/http/01_http.js:183:27)
error: Uncaught (in promise) Http: connection closed before message completed
at deno:core/01_core.js:106:46
at unwrapOpResult (deno:core/01_core.js:126:13)
at async respondWith (deno:extensions/http/01_http.js:183:27)
<process exit>
I’m at a loss for what to do here, especially since unhandled promise rejections cannot currently be caught globally (#7013)
Found older #10128 and #10380, but the code seems to have substantially changed since then, based on the stacktraces.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 26 (21 by maintainers)
@johnspurlock so with help from @lucacasonato and @ry we’ve debugged the problem.
Firstly, there’s a problem with stack trace that doesn’t give useful information, the best I could get was:
which points that there’s unresolved promise in the
computeResponsefunction.There’s also problem in your code in that you don’t await
writer.writeandwriter.closewhich both are promises and that was the root cause of the uncaught promise rejecetion.If you rewrite your code like so:
the problem goes away. (Writing of response needs to be done in an async IIFE because of WHATWG streams backpressure).
There’s also a bug in internal code that doesn’t properly clean up one resource that I’m working on a fix for,
but I’m afraid it might be released in 1.13.2 in a week as there’s some refactors I need to do before that can be fixed.This should be released in 1.13.1 after all.Thanks for providing this test case - this is quite an esoteric bug but I’m glad we got to the bottom of it.
Thanks @johnspurlock I’m getting the panic now. I will try to fix it for tomorrow.
Thanks for reports @johnspurlock @GJZwiers, I saw this issue today and it is something we’ll look into this week to release fixes for 1.13.1 on Monday. I’ll get back to you once I debug the problem, but from the initial investigation it seems to be an error that should be handled internally - looks like client is closing the connection before server writes full response.
If I reload the browser before the response from the server arrives I get the error too, how can I catch this error so that the application does not crash?
Example:
Start this with
deno run --allow-net app.tsIf I remove
await sleep(200);it also happens when I hold down the F5 key of the browser so that many requests are generated in a short time.Yes, it’s the same one, it’s actually called
responseBody.