Skip to content

[nextjs] api route not returning response or json once deployed to Vercel in latest 7.29.0 #6670

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

Closed
3 tasks done
wadehammes opened this issue Jan 5, 2023 · 6 comments · Fixed by #6674
Closed
3 tasks done
Assignees
Labels
Package: nextjs Issues related to the Sentry Nextjs SDK

Comments

@wadehammes
Copy link

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which package are you using?

@sentry/nextjs

SDK Version

7.29.0

Framework Version

NextJS 13.0.6

Link to Sentry event

No response

Steps to Reproduce

In the latest version, I am not getting json response from a 200 api route. There are no console logs though, the only way I found an error was via the component not loading as it awaits data from the api route before rendering.

I have deduced through updating one new package update at a time that Sentry SDK is the issue, and I suspect it has something to do with this:

feat(nextjs): Send events consistently on platforms that don't support streaming (#6578)

This is only happening once deployed to Vercel. Local work as intended. Downgrading to 7.28.1 api routes work as intended on both local and Vercel.

Expected Result

API routes return response as intended like in 7.28.1 when deployed to Vercel

Actual Result

Component doesn't load. I can't reproduce since this only happens on Vercel. There are no Sentry logs attached to this work yet either.

@wadehammes
Copy link
Author

Here is a the api route in question:

import { NextApiRequest, NextApiResponse } from "next";

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  const { secret, feedId, type } = req.query;

  // This secret key just allows us to make sure no one externally can hit this endpoint
  if (secret !== process.env.API_SECRET) {
    return res.status(401).json({ message: "Invalid token." });
  }

  if (!type) {
    return res.status(401).json({
      message: 'No type of either "reviews" or "feed" supplied as a parameter.',
    });
  }

  if (!feedId && type === "reviews") {
    return res.status(401).json({
      message: "No feed id supplied as a parameter to fetch reviews.",
    });
  }

  const apiUrl =
    feedId && type === "reviews"
      ? `https://embedsocial.com/admin/v2/api/reviews/reviews-filtered?feed_id=${feedId}&sort=created_on&per_page=200`
      : "https://embedsocial.com/admin/v2/api/reviews/feeds";

  try {
    const fetchReviews = await fetch(apiUrl, {
      method: "GET",
      headers: {
        Accept: "application/json",
        Authorization: `Bearer ${process.env.EMBED_SOCIAL_API_KEY}`,
        "Content-Type": "application/json; charset=utf-8",
      },
    });

    if (fetchReviews.ok) {
      const reviewsJson = await fetchReviews.json();

      if (reviewsJson.success) {
        res.status(200).json(reviewsJson);
      } else {
        res.status(400).json({ message: "Not able to fetch reviews json." });
      }
    }
  } catch (e) {
    res.status(400).json({ message: "Failed to fetch reviews." });
  }

  res.end();
};

@lforst
Copy link
Contributor

lforst commented Jan 6, 2023

Hi, thanks for surfacing this. I see the update could indeed cause problems in the wrong circumstances - luckily for you, the fix is relatively straightforward!

First, the Problem: To be able to flush events before the lambda on Vercel or AWS terminates, the SDK needs to wrap res.{send,json,end}() and turn them into async functions. In the example you shared, you're calling res.json() and res.end() sequentially and because these functions are now basically async, their execution order may be reversed (V8 probably decides on the order).

We should probably introduce a mechanism that preserves the execution order - even though it is generally not advised to call both .json() and .end() for the same request - not just in combination with the Sentry SDK but in general. The fix is therefore simply not doing that. You're already doing that by having a return statement in front of some res.json() calls. You can simply add it to the 200 and 400 response code paths and everything should work again.

We'll investigate if we can find a solution for this behaviour out of the box but please try out the proposed fix and let me know if it worked!

@wadehammes
Copy link
Author

@lforst that is good to know! Ill refactor now and let you know.

@lforst
Copy link
Contributor

lforst commented Jan 6, 2023

@wadehammes We'll probably release a fix for this on Monday. Thanks again for reporting this! In the meanwhile, the workaround I described should still work. (PR if you're interested #6674)

@lforst lforst self-assigned this Jan 6, 2023
@wadehammes
Copy link
Author

@wadehammes We'll probably release a fix for this on Monday. Thanks again for reporting this! In the meanwhile, the workaround I described should still work. (PR if you're interested #6674)

awesome. that fix worked and is a lot more straightforward. thank you

@lforst
Copy link
Contributor

lforst commented Jan 10, 2023

We just released a fix with version 7.30.0 of the SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Package: nextjs Issues related to the Sentry Nextjs SDK
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants