Skip to content

ERR_STREAM_WRITE_AFTER_END #6099

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
jessehansen opened this issue Oct 31, 2022 · 22 comments
Closed
3 tasks done

ERR_STREAM_WRITE_AFTER_END #6099

jessehansen opened this issue Oct 31, 2022 · 22 comments
Assignees
Labels
Package: nextjs Issues related to the Sentry Nextjs SDK

Comments

@jessehansen
Copy link

jessehansen commented Oct 31, 2022

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.17.2

Framework Version

NextJS 12.3.1

Link to Sentry event

No response

Steps to Reproduce

We're using Sentry with Next.JS on Vercel. Last week we updated from @sentry/nextjs version 7.13.0 to 7.16.0, and we started seeing some requests to API endpoints returning 500 errors without any corresponding events in Sentry. We have since updated to @sentry/[email protected] and are getting the same errors. The Function logs on Vercel show up with an error message for ERR_STREAM_WRITE_AFTER_END.

Additional Info:

  • Node Version: 16.16.0
  • Webpack version: 5.73.0

We tried removing all of the wrapping withSentry calls from our API routes, but it didn't stop these errors.

Expected Result

No internal stream errors output to Vercel's function logs.

Actual Result

(Line Breaks added for readability)

2022-10-31T19:44:11.763Z	44cbcf3d-c3f9-48cf-8aa2-659e324a5ed5	ERROR	Uncaught Exception 	
{"errorType":"Error",
"errorMessage":"write after end",
"trace":
["Error [ERR_STREAM_WRITE_AFTER_END]: write after end",
"    at new NodeError (node:internal/errors:372:5)",
"    at ServerResponse.end (node:_http_outgoing:846:15)",
"    at ServerResponse.apiRes.end (/var/task/node_modules/next/dist/server/api-utils/node.js:346:25)",
"    at ServerResponse.sentryWrappedEnd [as end] (/var/task/node_modules/@sentry/nextjs/cjs/config/wrappers/utils/responseEnd.js:29:22)",
"    at processTicksAndRejections (node:internal/process/task_queues:96:5)"]}
Unknown application error occurred

I believe this to be related to #4151

@tlenex
Copy link

tlenex commented Nov 3, 2022

Locking @sentry/nextjs at exact 7.14.0 seems to walk around the issue. Hopefully this will get fixed soon

@smeubank smeubank added the Package: nextjs Issues related to the Sentry Nextjs SDK label Nov 3, 2022
@jessehansen
Copy link
Author

We have been doing some more testing with this, and it looks like the issue is due to our apollo-server graphql endpoint being automatically instrumented with @sentry/nextjs > 7.14.0. When we add withSentry to the same endpoint, even in version 7.13.0, we start seeing this error. Perhaps the real issue is that sentry and Apollo Server don't play nice together in next API routes?

@jessehansen
Copy link
Author

Today we received this error in production, on 7.13.0. It happened on a simple status-check endpoint, which simply sends a 200 response with json data. I think this should be reproducible in a minimal next's environment on vercel with these 2 files and a cron job or something similar hitting the endpoint:

Here is the full source of the api route it happened on pages/api/status-check.ts:

import type { NextApiRequest, NextApiResponse } from "next";
import { withSentry } from "@sentry/nextjs";
import { logger } from "@:server/logger";

const statusCheck = async (
  _req: NextApiRequest,
  res: NextApiResponse
): Promise<any> => {
  try {
    res.json({ data: { up: true } });
    return res.status(200).end();
  } catch (err) {
    logger.warn("Error occurred during diag api check", err);
    return res
      .status(500)
      .send(
        "Error occurred while checking dependencies. Failed to connect to DB."
      );
  }
};

export default withSentry(statusCheck);

I can attach the source for the logger package as well, it's a simple Bunyan logger with a stream forwarding errors to Sentry:

import { createLogger } from "bunyan";
import type { LogLevel, Stream } from "bunyan";
import * as Sentry from "@sentry/nextjs";

const name =
  process?.env?.LOGGER_NAME ??
  process?.env?.npm_package_name ??
  "unknown logger";

const level: LogLevel =
  (process?.env?.LOGGER_LEVEL?.toLocaleLowerCase() as LogLevel) ?? "info";

const streams: Stream[] = [
  {
    level,
    stream: process.stdout,
  },
];

if (
  process.env.NODE_ENV === "production" &&
  process.env.DISABLE_SENTRY !== "1"
) {
  const sentryError = (err: any): Error => {
    if (err instanceof Error) return err;
    const error = new Error(err.message);
    error.name = err.name;
    error.stack = err.stack;
    // @ts-ignore sentry needs these props if they are present
    error.code = err.code;
    // @ts-ignore sentry needs these props if they are present
    error.signal = err.signal;
    return error;
  };

  streams.push({
    level: "error",
    type: "raw",
    stream: {
      // @ts-ignore bunyan WriteFn is not typed well
      write: ({ err, msg, tags, level: _level, ...extra }: object) => {
        if (err) {
          Sentry.captureException(sentryError(err), {
            extra,
            level: "error",
            tags,
          });
        } else {
          Sentry.captureMessage(msg, { extra, level: "error", tags });
        }
      },
    },
  });
}

export const logger = createLogger({
  name,
  streams,
});

logger.info({ message: `Logging with level '${level}'` });

@timfish
Copy link
Collaborator

timfish commented Nov 23, 2022

Why are you calling .end()?

To return an ok JSON response the nextjs docs suggest:

res.status(200).json({ data: { up: true } })

@311chaos
Copy link

Why are you calling .end()?

To return an ok JSON response the nextjs docs suggest:

res.status(200).json({ data: { up: true } })

You are correct in that you could write this differently, but are you suggesting that we should never use .end()?

Another example might be for when you need to respond with a 204.

res.status(204).end()

@timfish
Copy link
Collaborator

timfish commented Nov 23, 2022

Yes, if res.status(204).end() causes this issue, this would be considered a bug.

Why are you returning a value from the API route handler? None of the nextjs examples return anything. I think this may be causing an issue since Sentrys end wrapping is async.

try {
    res.json({ data: { up: true } });
    return res.status(200).end();
  } catch (err) {
    logger.warn("Error occurred during diag api check", err);
    return res
      .status(500)
      .send(
        "Error occurred while checking dependencies. Failed to connect to DB."
      );
  }

Should this not work without return?

@311chaos
Copy link

Yes, if res.status(204).end() causes this issue, this would be considered a bug.

Why are you returning a value from the API route handler? None of the nextjs examples return anything. I think this may be causing an issue since Sentrys end wrapping is async.

try {
    res.json({ data: { up: true } });
    return res.status(200).end();
  } catch (err) {
    logger.warn("Error occurred during diag api check", err);
    return res
      .status(500)
      .send(
        "Error occurred while checking dependencies. Failed to connect to DB."
      );
  }

Should this not work without return?

I am not certain on this (I will have to double check with the team after holiday), but I think this was in an attempt to fix the warning messages that get created after adding Sentry to our API routes: API resolved without sending a response for /api/xxx, this may result in stalled requests. Eventually we figured out that we had to set an env var for SENTRY_IGNORE_API_RESOLUTION_ERROR to make those stop barking.

@timfish
Copy link
Collaborator

timfish commented Nov 23, 2022

At this point return is only mildly suspicious to me because it differs from the examples. I'll not get a chance to try this myself until after the US vacation weekend.

Can you confirm that you only get the error in production? And is this only in production with Vercel? I haven't managed to reproduce this error yet but I haven't tried Vercel yet since it'll be much more painful to debug!

@jessehansen
Copy link
Author

Hi all - sorry for the delay, I was out for the holidays. I realize that calling .end() and returning were probably not the best, but I thought it was still interesting to have code for reproducing this issue that didn't include the rest of our stack. To answer your questions - I have only seen this error happen in production, but it doesn't happen every time - only occasionally. Our production is in Vercel, I don't have a different production environment to see if it happens.

@adarnon
Copy link

adarnon commented Nov 28, 2022

Happens to us as well. Running Next.js & custom Express server on a Debian Bullseye docker image and Node 18

@github-actions
Copy link
Contributor

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@timfish
Copy link
Collaborator

timfish commented Dec 20, 2022

I spent a day trying to reproduce this issue with no luck.

Any help to get this reproduced locally would be much appreciated!

@github-actions
Copy link
Contributor

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@adarnon
Copy link

adarnon commented Jan 11, 2023

This error is still happening to us in prod. Next.js v12, running on Node v18 & express custom server

@lforst
Copy link
Contributor

lforst commented Jan 11, 2023

@adarnon Can you try version 7.30.0of the SDK? I have a feeling that #6578 and #6592 resolve this to some degree.

@adarnon
Copy link

adarnon commented Jan 11, 2023

@lforst yeah - going to upgrade soon. Will update :)

@pcardune
Copy link

@lforst Upgrading to 7.30.0 seems to have worked for me.

@lforst
Copy link
Contributor

lforst commented Jan 17, 2023

@pcardune Awesome! Thanks for letting us know.

I will close this issue just to clean up our backlog a bit but feel free to ping us here in case this comes up again.

@lforst
Copy link
Contributor

lforst commented Jan 25, 2023

We suspect this is still happening on Vercel environments.

@lforst lforst reopened this Jan 25, 2023
@github-actions
Copy link
Contributor

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 24, 2023
@flpvsk
Copy link

flpvsk commented Dec 9, 2024

We suspect this is still happening on Vercel environments.

@lforst it is.. We are experience this issue on Vercel. Any recommended course of action?

  • "@sentry/nextjs": "7.119.0"
  • "next": "14.1.0"

@lforst
Copy link
Contributor

lforst commented Dec 10, 2024

@flpvsk I recommend upgrading to the latest version of the SDK. This is not something we will address in v7. It also technically shouldn't happen anymore I think.

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

No branches or pull requests

9 participants