Error fetching data on api route

Hey all,

I’m getting this error from the Moovweb logs: ReferenceError: fetch is not defined.

This error happens when trying to access some routes that fetch some data using the native fetch. These routes work normally with edge, but do not work on the branch-based environments that bypass edge. It’s my understanding that Next should handle polyfilling this for us, but doesn’t seem to be working when we bypass edge.

Any idea why this would be different without edge?

Sorry to hear about the problem. If you DM me the URL to your project page, I’ll take a look at the router and the configuration.

I don’t think being behind edge can affect this. I just deployed a simple next app and fetch is properly polyfilled on the server both when behind edge and not behind edge. Could it be that the deployment you’re testing which is failing uses a different version of Next? I think Next only recently started polyfilling fetch.

What happens when you try to access the permalink URL (which is not behind the edge) on the deployment which is successfully working on edge?

We are on Next 9.5.2 so I believe the version should be good.

When accessing the edge everything seems to work, but when accessing the permalink (such as this is where we start to see the error about fetch.

After doing a little troubleshooting together we realized that the code in question wasn’t part of the next app, but was running in a route handler. So in this case, Next.js wasn’t polyfilling fetch, and the solution was to import fetch from 'node-fetch'.

Hey Mark (and others) –

We’ve been working through this today and we are still running into an issue where the pages will not render on specific environments, but they will render at the edge.

At this point I believe it has something to do with renderNextPage which we are using here. It seems like that may not be functioning as expected for some reason outside of the edge environment?

Any insight you have would be extremely helpful. Here’s the code block in question – I make it all the way to the console log for NO DON'T USE RESORT TEMPLATE and get no errors in the build log.

const marketPage = async res => {
    const { cache, compute } = res;
        edge: {
            maxAgeSeconds: ONE_DAY,
            staleWhileRevalidateSeconds: ONE_HOUR,
    await compute(async request => {
        try {
            const useResortTemplate = await shouldUseResortTemplate(
                `USE RESORT TEMPLATE: ${JSON.stringify(useResortTemplate)}`

            if (useResortTemplate) {
                //render the /resort page and pass in the state and market
                console.log(`YES USE RESORT TEMPLATE`);

                renderNextPage('/resort', res, params => ({
                    state: params.state,
            } else {
                //render the /guest-market page and pass in the state and market
                console.log(`NO DON'T USE RESORT TEMPLATE`);
                    params => ({
                        state: params.state,
        } catch (e) {
            console.log('Error rendering market page ', e);

Here is the build log output:

16:57:39.391  INFO: RES: {"size":0,"timeout":0}
16:57:39.393  INFO: RES JSON: {"data":{"getMarketByUrl":{"market":{"useResortTemplate":false}}}}
16:57:39.393  INFO: USE RESORT TEMPLATE: false
16:57:42.551  INFO: info  - Loaded env from .env.local
16:57:42.567  INFO: info  - Loaded env from .env

As requested, I have set up a new environment called Debug and copied it from the default environment.

Also, here is the error we see in the browser (539 status code):
{"error":"UserCodeTimeoutError error"}

I think we’ve gotten to the bottom of it. There is a bug in the XDN where request.protocol is not properly set unless you run behind the edge. In your code you’re computing the URL for graphql using request.protocol, and using http:// when protocol is not provided. Since this results in an XDN serverless URL, and the XDN serverless layer does not send a response when it receives a non-secure request, the graphql call just hangs and the whole request eventually times out.

We are working on a fix for this and will post here when it’s released.

In the meantime, you could simply derive the protocol for the graphql URL using process.env.NODE_ENV (https for production, otherwise http).

Hey Mark – we provide the graphql using a .env variable (process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT in this case) based on environment, and that variable is always fully qualified with https – was there somewhere you were specifically seeing us construct a url this way? Or is there another piece that I’m missing?

We believe that the problem is in the protocol that the endpoint defaults to when req.protocol is not present. We just released 2.21.0 which sets req.protocol to either http or https depending on the downstream traffic. Could you test with that version?

I just deployed to our default environment (build #390) using v2.21.0 and the problem still persists. I think we are going to take the approach Mark recommends and just swap http/https based on local/deployed environments.

Just to close the loop on this –

We ended up keying off of a value in our local .env.local (so the env values would only exist when running locally). If that value is present (ie, local development) then it will set the protocol to http. Otherwise, it will set it to https. This appears to be working, thanks for the assistance!