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

False positive report of "API resolved without sending a response" #10439

Closed
gaku-sei opened this issue Feb 6, 2020 · 28 comments
Closed

False positive report of "API resolved without sending a response" #10439

gaku-sei opened this issue Feb 6, 2020 · 28 comments

Comments

@gaku-sei
Copy link

gaku-sei commented Feb 6, 2020

Bug report

Describe the bug

Api endpoint

Next will log the "API resolved without sending a response" warning even though the API endpoint always send a response back.

To Reproduce

Here the code that triggers the warning:

export default async function(req: NextApiRequest, res: NextApiResponse) {
  switch (req.method) {
    case "POST":
    case "OPTION": {
      try {
        const request = http.request( // Node core http module
          url,
          {
            headers: await makeHeaders(req, res),
            method: req.method,
          },
          response => {
            response.pipe(res);
          },
        );

        request.write(JSON.stringify(req.body));

        return request.end();
      } catch (error) {
        Log.error(error); // Can be a simple console.error too
      }

      return res.status(500).end();
    }
  }

  return res.status(405).end();
}

It seems that this endpoint will always send a response back.

Expected behavior

No warning

System information

  • OS: MacOS
  • Version of Next.js: 9.2.1
@timneutkens
Copy link
Member

This has been fixed in canary, can you try next@canary?

@idirmosh

This comment has been minimized.

@timneutkens
Copy link
Member

timneutkens commented Feb 6, 2020

@iddify please provide code instead of saying "same issue", it's unlikely that you're doing 100% exactly the same as the person that posts an issue.

@idirmosh

This comment has been minimized.

@idirmosh
Copy link

idirmosh commented Feb 6, 2020

UPDATE: i wasn't resolving the request, returning a 200 status code after the request finished removed the warning for me, MY BAD!

@gaku-sei
Copy link
Author

gaku-sei commented Feb 7, 2020

@timneutkens Thank you for the quick reply. Unfortunately 9.2.2-canary.12 doesn't solve the issue 😞

I don't know exactly how Next analyzes whether or not a route actually returns something, but it could be because of the callback in http.request or the try/catch ?

I also wonder if this couldn't be because of the http.request function that could "silently" fail and just not do anything 🤔

I will investigate a bit more 👍

@ijjk
Copy link
Member

ijjk commented Feb 7, 2020

@gaku-sei it is most likely caused by the callback as we can't detect you are still doing work in the API unless you return a promise and wait to resolve it until after the callback is fired e.g.

export default async function(req: NextApiRequest, res: NextApiResponse) {
  return new Promise(resolve => {
    switch (req.method) {
      case "POST":
      case "OPTION": {
        try {
          const request = http.request( // Node core http module
            url,
            {
              headers: await makeHeaders(req, res),
              method: req.method,
            },
            response => {
              response.pipe(res);
              resolve()
            },
          );

          request.write(JSON.stringify(req.body));
          request.end();
        } catch (error) {
          Log.error(error); // Can be a simple console.error too
          res.status(500).end();
          return resolve()
        }
      }
    }
    res.status(405).end();
    return resolve()
  })
}

@gaku-sei
Copy link
Author

gaku-sei commented Feb 7, 2020

@ijjk Thank you very much, that worked perfectly for me!

Issue solved 😄

@danielhusar
Copy link

I see the same warning with apollo-server-express.

@eric-burel
Copy link
Contributor

@danielhusar Any idea what could be the valid solution for apollo-server-express? Hitting the same issue "API resolved without sending a response for /, this may result in stalled requests.".
/ is not even called in my app, my endpoint is /api/graphql.

@danielhusar
Copy link

I havent been able to figure it out yet. Im considering to switch to express server to handle all requests. (Instead of just api)

@timneutkens
Copy link
Member

We're going to add a config option to opt-out of the warning for certain api routes if you're sure they resolve

@MuddyBootsCode
Copy link

I'm still running into this:

export default async function token(req, res) {
  try {
    const { user } = await auth0.getSession(req);

    if (user) {
      return new Promise((resolve, reject) => {
        fetch(`https://${process.env.domain}/oauth/token`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            grant_type: 'client_credentials',
            client_id: process.env.authClientID,
            client_secret: process.env.authClientSecret,
            audience: `https://${process.env.domain}/api/v2/`,
          }),
        })
        .then((res) => res.json())
        .then(({ access_token, scope, expires_in, token_type }) => {
          token = { access_token, scope, expires_in, token_type };
          console.log(token)
          resolve(token);
        })
        .catch(err => {
          reject(err);
        })
      })
    }
    else {
      throw new Error('No User');
    }
  } catch (error) {
    console.error(error)
    res.status(error.status || 500).end(error.message)
  }
}

@timneutkens
Copy link
Member

export default async function token(req, res) {
  try {
    const { user } = await auth0.getSession(req);

    if(!user) {
      throw new Error('No User');
    }

    const result = await fetch(`https://${process.env.domain}/oauth/token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        grant_type: 'client_credentials',
        client_id: process.env.authClientID,
        client_secret: process.env.authClientSecret,
        audience: `https://${process.env.domain}/api/v2/`,
      }),
    })
    const { access_token, scope, expires_in, token_type } = await result.json()


    return { access_token, scope, expires_in, token_type }
  } catch (error) {
    console.error(error)
    return res.status(error.status || 500).end(error.message)
  }
}

This should solve your case, but you can now disable the warning also: https://nextjs.org/docs/api-routes/api-middlewares

// export this from the api route
export const config = {
  api: {
    externalResolver: true,
  },
}

@tettoffensive
Copy link

I'm not sure I understand. I'm getting it with this code which I got from the example for firebase server authentication:

pages/api/login.ts:

import commonMiddleware from '../../middleware/commonMiddeware';
import { verifyIdToken } from '../../firebase/auth/admin';

const handler = async (req, res) => {
  if (!req.body) {
    return res.status(400);
  }

  const { token } = req.body;

  try {
    const decodedToken = await verifyIdToken(token);
    req.session.decodedToken = decodedToken;
    req.session.token = token;
    return res.status(200).json({ status: true, decodedToken });
  } catch (error) {
    return res.status(500).json({ error });
  }
};

export default commonMiddleware(handler);

@timneutkens
Copy link
Member

Looks like you're not finishing the request when a body is not set:

  if (!req.body) {
    return res.status(400);
  }

Should be:

  if (!req.body) {
    return res.status(400).send({});
  }

@Manubi
Copy link

Manubi commented Aug 2, 2020

Looks like you're not finishing the request when a body is not set:

  if (!req.body) {
    return res.status(400);
  }

Should be:

  if (!req.body) {
    return res.status(400).send({});
  }

Have the same problem and the above fix isn't working for me. :/

@viniciusbitt
Copy link

I have the same problem. The message just a warning or can it really give you problems?

@miguel9554
Copy link

I'm having the same problem. Why is this issue closed? Is this a problem from Next server or am I doing something wrong?

@rahimimo3
Copy link

+1 same for me

@damiensedgwick
Copy link

I am getting this same warning too however I am getting the data I expect to revieve in the console :/

@parabuzzle
Copy link

Updated to next@canary and I'm still seeing this error.

here's my handler:

const trades = mongoMiddleware(async (req, res, connection, models) => {
  const {
    method
  } = req

  apiHandler(res, method, {
    GET: (response) => {
      models.Trade.find({}, (error, trade) => {
        if (error) {
          connection.close();
          response.status(500).json({ error });
        } else {
          response.status(200).json(trade);
          connection.close();
        }
      })
    }
  });
})

When I hit my route I get a json array returned with all the trades.. but I get this in the console:

API resolved without sending a response for /api/trades, this may result in stalled requests.

@rene-demonsters
Copy link

People still running into this issue might want to look closely at: #10439 (comment) and #11380

If you're using an externalResolver (such as Express), nextjs can't detect that the API response has been send. At the bottom of #10439 (comment) @timneutkens explains how you can disable the warning if that is indeed the case.

@eric-burel
Copy link
Contributor

eric-burel commented Nov 20, 2020

I don't think it explains why I would get the warning for API resolved without sending a response for /, this may result in stalled requests. even if I don't query it and it doesn't exist in my app

@rista404
Copy link

I had the same issue with the following code:

export default async (req: NextApiRequest, res: NextApiResponse) => {
	if (req.method === 'POST') {
		handlePost(req, res)
		return
	}

	if (req.method === 'GET') {
	       handleGet(req, res)
	       return
	}

	res.status(405).send('Method not allowed')
}

What solved it for me was awaiting both handlers, like so: await handlePost(req, res).

@ghost
Copy link

ghost commented Apr 19, 2021

The problem was that (req, res) => ... neeeds to return some default response.

E.g. return res.status(200).json({ msg: "Works"});

@imamabdulazis
Copy link

@gaku-sei it is most likely caused by the callback as we can't detect you are still doing work in the API unless you return a promise and wait to resolve it until after the callback is fired e.g.

export default async function(req: NextApiRequest, res: NextApiResponse) {
  return new Promise(resolve => {
    switch (req.method) {
      case "POST":
      case "OPTION": {
        try {
          const request = http.request( // Node core http module
            url,
            {
              headers: await makeHeaders(req, res),
              method: req.method,
            },
            response => {
              response.pipe(res);
              resolve()
            },
          );

          request.write(JSON.stringify(req.body));
          request.end();
        } catch (error) {
          Log.error(error); // Can be a simple console.error too
          res.status(500).end();
          return resolve()
        }
      }
    }
    res.status(405).end();
    return resolve()
  })
}

Awesome, work perfectly sir😃.

Flecart pushed a commit to csunibo/note-website that referenced this issue Nov 7, 2021
In order i have done these things with this commit:
1. Fix svg import creating a custom d.ts module and adding includes in tscondig.json 2. Add interfaces and models for the database (added stuff for remote database
3. Added logic and VALIDATORS for uploading notion links
4. fixed a bug described here vercel/next.js#10439 (comment), for sections ts and courses ts, Senza questa promise arrivava il warning: ```API resolved without sending a response for /api/sections, this may result in stalled requests.``` Ossia non sapeva se sta ancora aspettando o no, sta cosa risolve.

I made many todos: Like moving the validators to model level
Flecart pushed a commit to csunibo/note-website that referenced this issue Nov 7, 2021
In order i have done these things with this commit:
1. Fix svg import creating a custom d.ts module and adding includes in tscondig.json
2. Add interfaces and models for the database (added stuff for remote database
3. Added logic and VALIDATORS for uploading notion links
4. fixed a bug described here vercel/next.js#10439 (comment), for sections ts and courses ts, Senza questa promise arrivava il warning: ```API resolved without sending a response for /api/sections, this may result in stalled requests.``` Ossia non sapeva se sta ancora aspettando o no, sta cosa risolve.

I made many todos: Like moving the validators to model level
Flecart added a commit to csunibo/note-website that referenced this issue Nov 7, 2021
* feat: add basic mongo API

Created courses and sections api entries with NEXT js.
Doesn't have custom filtering or queries integrated with Mongo, should make them by myself. By now i'm just using standard next.js query with mongo params.

* refactor(mongo): create main API function, and mongo type

created single function that handles native database connection, and the type for our responses

* refactor(mongo): delete mongodb package for mongoose

added database models, fix for svg typescript import, and database connection

* feat: add upload notion links

In order i have done these things with this commit:
1. Fix svg import creating a custom d.ts module and adding includes in tscondig.json
2. Add interfaces and models for the database (added stuff for remote database
3. Added logic and VALIDATORS for uploading notion links
4. fixed a bug described here vercel/next.js#10439 (comment), for sections ts and courses ts, Senza questa promise arrivava il warning: ```API resolved without sending a response for /api/sections, this may result in stalled requests.``` Ossia non sapeva se sta ancora aspettando o no, sta cosa risolve.

I made many todos: Like moving the validators to model level
@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 28, 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

No branches or pull requests