Skip to content
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

Nondescriptive Typeerror: Cannot read properties of undefined (reading 'reason') #1776

Closed
Ethan-Arrowood opened this issue Nov 17, 2022 · 10 comments · Fixed by #1787
Closed
Assignees
Labels
bug Something isn't working

Comments

@Ethan-Arrowood
Copy link
Collaborator

Ethan-Arrowood commented Nov 17, 2022

Bug Description

Got a strange error using fetch,

TypeError: fetch failed
    at fetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/index.js:105:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async getLatestVersionOfMajor (/home/runner/work/api/api/scripts/build-container/scripts/update-node.js:48:20)
    at async module.exports (/home/runner/work/api/api/scripts/build-container/scripts/update-node.js:139:22)
    at async eval (eval at callAsyncFunction (/home/runner/work/_actions/actions/github-script/v6/dist/index.js:13356:16), <anonymous>:4:1)
    at async main (/home/runner/work/_actions/actions/github-script/v6/dist/index.js:13452:20) {
  cause: TypeError: Cannot read properties of undefined (reading 'reason')
      at makeAppropriateNetworkError (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/response.js:467:58)
      at schemeFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:788:12)
      at /home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:605:22
      at mainFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:655:7)
      at httpRedirectFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:1230:10)
      at httpFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:1091:24)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at async schemeFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:889:14)
      at async /home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:605:16
      at async mainFetch (/home/runner/work/api/api/scripts/build-container/node_modules/undici/lib/fetch/index.js:589:16)
}

The code is private, but the line that caused this is: const response = await fetch(`https://nodejs.org/dist/latest-v${major}.x`);. I'm investigating now. Most likely an issue on my end but we may be able to benefit from a better error message here.

Reproducible By

Expected Behavior

Logs & Screenshots

Environment

Additional context

@Ethan-Arrowood Ethan-Arrowood added the bug Something isn't working label Nov 17, 2022
@Ethan-Arrowood Ethan-Arrowood changed the title Nondescriptive error Nondescriptive Typeerror: Cannot read properties of undefined (reading 'reason') Nov 17, 2022
@Ethan-Arrowood Ethan-Arrowood self-assigned this Nov 17, 2022
@KhafraDev
Copy link
Member

This is an issue in fetch where the controller doesn't have a terminated property (likely got removed a while ago)

: makeNetworkError(fetchParams.controller.terminated.reason)

@Ethan-Arrowood
Copy link
Collaborator Author

Hmm okay. I need to crawl the call stack for this then and see why the controller doesn't have a terminated property. It might be a simple ?. fix too

@Ethan-Arrowood
Copy link
Collaborator Author

This is related to redirect follow I think

fetch https://nodejs.org/dist/latest-v16.x

// Error
fetch https://nodejs.org/dist/latest-v16.x/

// Actual webpage

Notice the trailing / in the url. Its the only difference

@Ethan-Arrowood
Copy link
Collaborator Author

node-fetch does not have this problem

@KhafraDev
Copy link
Member

Yeah, it's definitely related to redirects; I couldn't figure out a way to replicate it locally though.

The actual issue is that the connection is being destroyed due to the redirect mode being set to 'follow'. Here's a diff that fixes the issue, but definitely breaks some other things.

diff --git a/lib/fetch/index.js b/lib/fetch/index.js
index 6c67c1e..2ddbcfd 100644
--- a/lib/fetch/index.js
+++ b/lib/fetch/index.js
@@ -1069,7 +1069,7 @@ async function httpFetch (fetchParams) {
     // encouraged to, transmit an RST_STREAM frame.
     // See, https://github.com/whatwg/fetch/issues/1288
     if (request.redirect !== 'manual') {
-      fetchParams.controller.connection.destroy()
+      // fetchParams.controller.connection.destroy()
     }

     // 2. Switch on request’s redirect mode:
@@ -1562,7 +1562,7 @@ async function httpNetworkFetch (
   includeCredentials = false,
   forceNewConnection = false
 ) {
-  assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed)
+  // assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed)

   fetchParams.controller.connection = {
     abort: null,
diff --git a/lib/fetch/response.js b/lib/fetch/response.js
index 9c9d628..a991ea0 100644
--- a/lib/fetch/response.js
+++ b/lib/fetch/response.js
@@ -436,7 +436,7 @@ function makeAppropriateNetworkError (fetchParams) {
   // otherwise return a network error.
   return isAborted(fetchParams)
     ? makeNetworkError(new DOMException('The operation was aborted.', 'AbortError'))
-    : makeNetworkError(fetchParams.controller.terminated.reason)
+    : makeNetworkError(new TypeError('request failed'))
 }

 // https://whatpr.org/fetch/1392.html#initialize-a-response

@KhafraDev
Copy link
Member

Actually all the tests pass.

cc @ronag

@brian6932
Copy link

brian6932 commented Nov 21, 2022

I have this as well
Downgrading from [email protected] -> [email protected] is a temp fix

@repsac-by
Copy link
Contributor

repsac-by commented Nov 28, 2022

@KhafraDev

Yeah, it's definitely related to redirects; I couldn't figure out a way to replicate it locally though.

repro:

const { createServer } = require('node:http');
const { fetch } = require('.');


createServer((req, res) => {
	if (req.url === '/redirect') {
		res.statusCode = 301;
		res.setHeader('location', '/redirect/');
		res.write('<a href="/redirect/">Moved Permanently</a>');
		setTimeout(() => res.end(), 500);
		return;
	}

	res.write(req.url);
	res.end();
}).listen(3000, async () => {
	console.log('listen');

	const resp = await fetch('http://localhost:3000/redirect');
	console.log(await resp.text());
});

broken on commit 6883ba5

@KhafraDev
Copy link
Member

Thanks! I figured out the reasoning this broke too. We destroy the old connection on redirect, causing the condition in 6883ba5 to get triggered. Will post a PR to fix this soon.

jaslong added a commit to plasmicapp/unfetch that referenced this issue Jan 18, 2023
Due to a bug in undici (nodejs/undici#1776)
that is affecting many versions of Node and Next.js,
we want a workaround to ensure our users don't see this.

Therefore, we're forking isomorphic-unfetch to always use node-fetch
on Node to avoid falling back to global.fetch (undici).

Also, isomorphic-unfetch was polyfilling, which we want to avoid.
jaslong added a commit to plasmicapp/unfetch that referenced this issue Jan 19, 2023
Due to a bug in undici (nodejs/undici#1776)
that is affecting many versions of Node and Next.js,
we want a workaround to ensure our users don't see this.

Therefore, we're forking isomorphic-unfetch to always use node-fetch
on Node to avoid falling back to global.fetch (undici).

Also, isomorphic-unfetch was polyfilling, which we want to avoid.
jaslong added a commit to plasmicapp/unfetch that referenced this issue Jan 19, 2023
Due to a bug in undici (nodejs/undici#1776)
that is affecting many versions of Node and Next.js,
we want a workaround to ensure our users don't see this.

Therefore, we're forking isomorphic-unfetch to always use node-fetch
on Node to avoid falling back to global.fetch (undici).

Also, isomorphic-unfetch was polyfilling, which we want to avoid.
@Vincenius
Copy link

If someone else also stumbles upon this - I had the same error (Cannot read properties of undefined (reading 'reason')) on calling a Next.js api endpoint on prod.

The solution for me was to remove the trailingSlash: true from the next.config file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants