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

fetchNextData error handling fails with TypeError: Attempted to assign to readonly property. #11608

Closed
pjaws opened this issue Apr 2, 2020 · 10 comments · Fixed by #16051
Closed
Assignees
Milestone

Comments

@pjaws
Copy link
Contributor

pjaws commented Apr 2, 2020

Bug report

Describe the bug

I woke up this morning to find that some of our site's CTA links (using 'next/link') were broken in mobile browsers, displaying "An unexpected error has occurred" to the user. The only thing I could find in Rollbar was this error: TypeError: Attempted to assign to readonly property..

Testing locally with iOS Simulator, I traced it to this line in .next/static/development/pages/_app.js:

      err.code = 'PAGE_LOAD_ERROR';

Here is the full function where the error is occurring:

function fetchNextData(pathname, query, isServerRender, cb) {
  var attempts = isServerRender ? 3 : 1;

  function getResponse() {
    return fetch(utils_1.formatWithValidation({
      // @ts-ignore __NEXT_DATA__
      pathname: "/_next/data/".concat(__NEXT_DATA__.buildId).concat(pathname, ".json"),
      query: query
    }), {
      // Cookies are required to be present for Next.js' SSG "Preview Mode".
      // Cookies may also be required for `getServerSideProps`.
      //
      // > `fetch` won’t send cookies, unless you set the credentials init
      // > option.
      // https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
      //
      // > For maximum browser compatibility when it comes to sending &
      // > receiving cookies, always supply the `credentials: 'same-origin'`
      // > option instead of relying on the default.
      // https://github.com/github/fetch#caveats
      credentials: 'same-origin'
    }).then(function (res) {
      if (!res.ok) {
        if (--attempts > 0 && res.status >= 500) {
          return getResponse();
        }

        throw new Error("Failed to load static props");
      }

      return res.json();
    });
  }

  return getResponse().then(function (data) {
    return cb ? cb(data) : data;
  })["catch"](function (err) {
    // We should only trigger a server-side transition if this was caused
    // on a client-side transition. Otherwise, we'd get into an infinite
    // loop.
    if (!isServerRender) {
      err.code = 'PAGE_LOAD_ERROR';
    }

    throw err;
  });
}

The page I am attempting to transition to is using getServerSideProps to check the user's a/b test cookie and redirect them based on the result:

export const getServerSideProps = async (ctx) => {
  const expVariantId = getOrSetGoCookie(ctx);

  if (expVariantId === '1') {
    const { res, query } = ctx;

    res
      .writeHead(307, {
        Location: `${process.env.HI_BASE_URL}/signup?${queryString.stringify(query)}`,
      })
      .end();

    return { props: {} };
  }

  return { props: { expVariantId } };
};

This issue never occurs when navigating to the page directly or using a standard anchor tag - only when using 'next/link'.

Here is the link for reference:

            <Link href="/start" as={`${process.env.HI_BASE_URL}/start`} passHref>
              <Button as="a" variant="green" width={1} mt={6} data-testid="GetStartedA">
                Get Started
              </Button>
            </Link>

To Reproduce

Obviously, this is a sort of complicated example, and I'm not exactly sure what's causing the initial error. Let me know if you need more information, and I can try to create an example repo when I'm able to.

Expected behavior

It would seem there are 2 issues here. One is that an error is occurring during when clicking a next/link to a page using getServerSideProps to redirect. The other is that during the handling of this error, another error is thrown when attempting to set the value of err.code.

I would expect to get information about what the error is, if it's something caused by my code, but we never make it that far.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: iOS
  • Browser: Safari (reported on Chrome too)
  • Version of Next.js: 9.3.3

Additional context

Thank you! Again, happy to provide any more detail necessary.

@marco-koenen
Copy link

marco-koenen commented May 1, 2020

Have you been able to correct this bug yet? I have encountered the same error. (only in production mode)

When I switch from getStaticProps

export async function getStaticProps() {
  const page = (await backend.client.pages().slug('test')) || null
  return { props: { page } }
}

to getInitialProps the error does not occur.

static async getInitialProps() {
    const page = (await backend.client.pages().slug('test')) || null
    return { page }
  }

But unfortunately this is no solution for me, because I need all pages as static pages.

@pjaws
Copy link
Contributor Author

pjaws commented May 1, 2020

I actually switched to getInitialProps for other reasons, but the solution for the error that was causing this error was to stop using 'next/link'/client-side routing. I have had so many issues with those links - especially on mobile devices. "An unexpected error has occurred", links just plain doing nothing when you click them, etc.

@saleebm
Copy link

saleebm commented May 9, 2020

Same problem here, ended up using the normal html anchor instead of the Link from 'next/link' and no problem.

I received the same error as above, PAGE_LOAD_ERROR. Redirect on getServerSideProps did not redirect, initial error showed up as "attempt to assign to readonly type... native code"


I was able to make a basic repro. Please see context below for info.

Repro here

edit: some additional context:

I am using the next preview version of Next.js (^9.3.7-canary.17) as of now. I enabled React strict mode from the config.

Strangely, the error only happens in Safari. In Chrome, the route works fine, Firefox sees a white page for a second but no error thrown. As also mentioned above, the author of this issue noticed the error in an iOS simulator.


2nd edit:

On Firefox, when clicking the link to My Account from the repro above, it reloads the page once. Clicking it again will go to the redirected route though.

Environment:

macOS Catalina Beta 10.15.5

Node v12.16.3

@marco-koenen
Copy link

Oh, I forgot to answer that. I have solved the problem in the meantime - I have executed Next in a different folder. (/frontend instead of /src) By switching back, it also worked in production mode.

@Timer Timer modified the milestones: 9.4, 9.4.1, 9.4.2 May 9, 2020
@Timer Timer modified the milestones: 9.4.2, 9.4.3 May 20, 2020
@saleebm
Copy link

saleebm commented May 27, 2020

I can confirm that this is no longer an issue with the latest canary, 9.4.3-canary.1

Thank you!

@Timer Timer modified the milestones: 9.4.3, 9.4.4 May 28, 2020
@revolunet
Copy link

revolunet commented Jun 17, 2020

Having the same fatal error on Safari/Edge with [email protected] when:

  • trying to click a next/link that has href="/projects"
  • that /projects returns a non JSON value so that the res.json() in getResponse fails (a 302 in my case)

this ultimately triggers the catch where error.code is rewritten which seems not allowed in Edge/Safari ('readonly property)

(Exist in dev and prod)

@Timer Timer modified the milestones: 9.4.5, 9.x.x Jun 17, 2020
@Timer Timer added good first issue Easy to fix issues, good for newcomers kind: bug and removed kind: story labels Jun 17, 2020
@revolunet
Copy link

Ok so for me this was related to this issue : #12409

@Timer Timer removed the good first issue Easy to fix issues, good for newcomers label Jul 21, 2020
@Timer Timer self-assigned this Jul 21, 2020
@Timer Timer modified the milestones: 9.x.x, iteration 6 Jul 21, 2020
@Timer Timer modified the milestones: iteration 5, iteration 6 Jul 21, 2020
@Timer Timer added the point: 2 label Aug 10, 2020
Timer added a commit to Timer/next.js that referenced this issue Aug 10, 2020
Safari now treats Error#code as a readonly property, which means we can no longer override it.
This PR replaces the now-reserved property with a Symbol descriptor.

It also adds new production tests for this behavior to ensure they're ran against all major browsers (Safari included) in our E2E CI.

---

Fixes vercel#11608
@Timer Timer modified the milestones: iteration 6, iteration 7 Aug 10, 2020
@Timer
Copy link
Member

Timer commented Aug 10, 2020

This was fixed in next@^9.5.2-canary.15 and newer. Please upgrade and let us know if it works for you!

@luismramirezr
Copy link

I had this problem in [email protected]. It works with [email protected]. Thanks!

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants