remix: Remix crashes with web-fetch 4.3.2/1.8.2

What version of Remix are you using?

1.8.2

Steps to Reproduce

See sandbox: https://codesandbox.io/p/sandbox/solitary-wave-1l0skr Failing test PR: https://github.com/remix-run/remix/pull/4994

  1. Observe exit code 1 (remix crashes, premature close error) when fetcher loads from /load.tsx route, which calls fetch from a Google drive URL
  2. Go to load.tsx, uncomment the import that uses web-fetch 4.3.1
  3. Remix no longer crashes

Expected Behavior

web-fetch’s fetch should work, without crashing remix, returning a valid HTML result

Actual Behavior

remix crashes, exit code 1

/project/sandbox/node_modules/@remix-run/node/node_modules/@remix-run/web-fetch/src/fetch.js:342
                                const error = Object.assign(new Error('Premature close'), {
                                ^
Error: Premature close
    at TLSSocket.onSocketClose (/project/sandbox/node_modules/@remix-run/node/node_modules/@remix-run/web-fetch/src/fetch.js:342:33)
    at TLSSocket.emit (node:events:525:35)
    at node:net:757:14
    at TCP.done (node:_tls_wrap:584:7)
error Command failed with exit code 1.

Related issues:

https://github.com/remix-run/remix/issues/4737

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 6
  • Comments: 30 (18 by maintainers)

Commits related to this issue

Most upvoted comments

I’m surprised that something that crashes Remix isn’t getting any attention.

PR created with a possible fix: https://github.com/remix-run/web-std-io/pull/29

Plz review

@brophdawg11 no errors so far 👍

We’ve had this issue (intermittently on prod only) and we’ve updated to 1.19.2-pre.0 and are testing it out now. Will update this issue if we continue to experience the Premature close error

The error does not occur if you have connection: keep-alive in the headers. I think axios sets that automatically.

FYI… Here’s the diff between 4.3.1 and 4.3.2

fetch.js

diff --git a/src/fetch.js b/src/fetch.js
index v4.3.1..v4.3.2 100644
--- a/src/fetch.js
+++ b/src/fetch.js
@@ -346,13 +346,8 @@
 			}
 		};
 
-		socket.prependListener('close', onSocketClose);
-
-		request.on('abort', () => {
-			socket.removeListener('close', onSocketClose);
-		});
-
-		socket.on('data', buf => {
+		/** @param {Buffer} buf */
+		const onData = buf => {
 			properLastChunkReceived = Buffer.compare(buf.slice(-5), LAST_CHUNK) === 0;
 
 			// Sometimes final 0-length chunk and end of message code are in separate packets
@@ -364,6 +359,14 @@
 			}
 
 			previousChunk = buf;
+		};
+
+		socket.prependListener('close', onSocketClose);
+		socket.on('data', onData);
+
+		request.on('close', () => {
+			socket.removeListener('close', onSocketClose);
+			socket.removeListener('data', onData);
 		});
 	});
 }

request.js

diff --git a/src/request.js b/src/request.js
index v4.3.1..v4.3.2 100644
--- a/src/request.js
+++ b/src/request.js
@@ -38,6 +38,7 @@
  * @property {string} method
  * @property {RequestRedirect} redirect
  * @property {globalThis.Headers} headers
+ * @property {RequestCredentials} credentials
  * @property {URL} parsedURL
  * @property {AbortSignal|null} signal
  * 
@@ -135,6 +136,7 @@
 			method,
 			redirect: init.redirect || input.redirect || 'follow',
 			headers,
+			credentials: init.credentials || 'same-origin',
 			parsedURL,
 			signal: signal || null
 		};
@@ -169,7 +171,7 @@
 	 */
 
 	get credentials() {
-		return "same-origin"
+		return this[INTERNALS].credentials
 	}
 
 	/**