vercel / next.js

The React Framework
https://nextjs.org
MIT License
123.53k stars 26.35k forks source link

500 Error - "static responses cannot be piped. This is a bug in Next.js" #33292

Open imconfused218 opened 2 years ago

imconfused218 commented 2 years ago

Run next info (available from version 12.0.8 and up)

No response

What version of Next.js are you using?

12.0.7

What version of Node.js are you using?

14.15.0

What browser are you using?

Chrome

What operating system are you using?

MacOS

How are you deploying your application?

Custom server/Other platform

Describe the Bug

Experiencing intermittent 500s in production across all SSG pages with revalidation. When checking server logs, found this errror:

Error: invariant: static responses cannot be piped. This is a bug in Next.js
at RenderResult.pipe (/var/app/node_modules/next/dist/server/render-result.js:18:19)
at Object.sendRenderResult (/var/app/node_modules/next/dist/server/send-payload.js:58:22)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:95:5)

Looking a little deeper into the render-result file it appears that the result might be an empty string.

Also the 500 errors reported from users are blank with the text "Internal Server Error" and not our custom error page.

Expected Behavior

Expect a successfully rendered page or the custom error page.

To Reproduce

Unfortunately, haven't been able to reproduce this issue due to it's inconsistency and can't seem to find any pattern other than all the 500s are from SSG pages.

balazsorban44 commented 2 years ago

Could you at least share your next.config.js file?

huozhi commented 2 years ago

Could you also share the snippet of your custom error page with next.config.js together?

imconfused218 commented 2 years ago

Sure, happy too. Thanks for the quick response. next.config.js

'use strict';

const webpack = require('webpack');
const log = require('./utils/logger');
const { formatRedirects } = require('./utils/redirects');
const redirects = require('./config/redirects.json');
const cp = require('child_process');
const config = require('./config/app');
const API_ROOT = config.get('api.host');
const appData = require('./config/appData')
const env = {
    API_ROOT: JSON.stringify(API_ROOT),
};

const APP_ENV = config.get('env');
const isProd = APP_ENV === 'production';
const CDN = config.get('application.cdn');
const withBundleAnalyzer = require('@next/bundle-analyzer')({
    enabled: process.env.BUNDLE_ANALYZE === 'true',
});

process.env.APP_DATA = JSON.stringify(appData);
const formattedRedirects = formatRedirects(redirects);

module.exports = withBundleAnalyzer({
    assetPrefix: CDN,
    async redirects() {
        return formattedRedirects;
    },
    webpack: (config, { isServer }) => {
        // Plugins
        config.plugins.push(new webpack.DefinePlugin(env));
        config.plugins.push(new webpack.NormalModuleReplacementPlugin(/\/iconv-loader$/, 'node-noop'));
        config.plugins.push(new webpack.NormalModuleReplacementPlugin(/whatwg-fetch/, 'node-noop'));
        config.plugins.push(new webpack.NormalModuleReplacementPlugin(/promise-polyfill/, 'node-noop'));

        const minimizer = config.optimization && config.optimization.minimizer && config.optimization.minimizer[0];
        if (minimizer && minimizer.options && minimizer.options.terserOptions) {
            minimizer.options.terserOptions.keep_fnames = true;
            minimizer.options.terserOptions.keep_classnames = true;
            // Because this is a thing we still have to do in 2018 https://github.com/mishoo/UglifyJS2/issues/1753
            minimizer.options.terserOptions.safari10 = true;
        }

        log.info(`Building with env ${APP_ENV} for ${isServer ? 'server' : 'client'}`);
        if (isProd) {
            const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin');

            let codeVersion;
            try {
                codeVersion = cp
                    .execSync('git rev-parse HEAD', {
                        cwd: __dirname,
                        encoding: 'utf8',
                    })
                    .trim();
            } catch (err) {
                log.error('Error getting revision', err);
                process.exit(1);
            }

            config.devtool = 'hidden-source-map';
            log.info(`Setting code version to ${codeVersion}`);
            config.plugins.push(
                new webpack.DefinePlugin({
                    CODE_VERSION: JSON.stringify(codeVersion),
                })
            );

            if (!process.env.BUNDLE_ANALYZE) {
                config.plugins.push(
                    new RollbarSourceMapPlugin({
                        accessToken: appData.ROLLBAR_SERVER,
                        version: codeVersion,
                        publicPath: `${CDN}/_next/`,
                        silent: false,
                    })
                );
            }
        }

        config.resolve.fallback = {
            fs: false,
        };

        return config;
    },
    publicRuntimeConfig: appData,
});

_error.js

// @flow
import React, { useEffect } from 'react';
import GlobalWrapper from '../contexts/global-wrapper';
import Layout from '../layouts/static-main';
import NotFound from '../components/page/not-found';
import { CustomError } from '../utils/error/custom-error';

import type { GetInitialPropsPage } from '../types/next';

type Props = {
    statusCode: number,
    err: ?Error,
    serverLogged: boolean,
    ...
};

type Params = { ... };

const ErrorPage: GetInitialPropsPage<Props, Params> = ({ err, serverLogged, statusCode }) => {
    useEffect(() => {
        if (window.Rollbar && err && !serverLogged) {
            window.Rollbar.error(err.toString());
        }
    }, [err, serverLogged]);

    if (statusCode < 500) {
        const layoutProps = {
            noContainer: true,
            title: 'MySite',
            description:
                'MySite Description',
            proUpsell: 'TRY FOR FREE',
        };
        return (
            <GlobalWrapper>
                <Layout {...layoutProps}>
                    <NotFound title="410 - Page gone" />
                </Layout>
            </GlobalWrapper>
        );
    }

    return (
        <div className="page-not-found">
            <div>
                <div style={{ textAlign: 'center', paddingTop: '24px' }}>
                    <h2>Internal Server Error</h2>
                    <p>
                        We're sorry. Something went wrong with your request. Please try again or contact us at{' '}
                        <a href="mailto:feedback@mysite.com">feedback@mysite.com</a> if the issue
                        persists.
                    </p>
                    <img src="https://static-assets/assets/img/500.png" />
                </div>
            </div>
        </div>
    );
};

ErrorPage.getInitialProps = async ({ res, req, err }) => {
    let serverLogged = false;
    let statusCode = res?.statusCode || 500;
    if (res && err) {
        const rollbarOptions = {
            payload: {},
            level: 'error',
        };
        if (err instanceof CustomError) {
            if (err.statusCode) {
                res.statusCode = err.statusCode;
                statusCode = err.statusCode;
            }
            rollbarOptions.payload = err.options || {};
        }

        const { reportRollbar } = require('../utils/rollbar/server');

        if (req) {
            await reportRollbar(err, req, rollbarOptions);
        }

        // eslint-disable-next-line
        console.error(err);
        serverLogged = true;
    }
    return {
        err,
        serverLogged,
        statusCode,
    };
};

export default ErrorPage;

I'll also work on getting a reproducing example to show.

Downchuck commented 2 years ago

I'm seeing failures out of the box with ​npx create-next-app@latest

 ​"dependencies": {
   ​"next": "12.0.9",
   ​"react": "^18.0.0-rc.0",
   ​"react-dom": "^18.0.0-rc.0"
 ​},

Like it's just not working -- with SSR turned off:

TypeError: Cannot read properties of null (reading 'useContext')

And then with SSR turned on, I get the invariants error.

module.exports = {
  reactStrictMode: true,
  experimental: {
    concurrentFeatures: true,
    serverComponents: true
  }
}

I didn't see if the original poster was trying to use React 18. There's something just really going wrong on my machine with Next 12... I've tried a couple versions of node, and I bumped my os version up -- this is on alpine linux via wsl.

huozhi commented 2 years ago

@Downchuck you cannot use useContext with server components, it's not supported yet

Downchuck commented 2 years ago

@huozhi I mean to say something went wrong with just the standard create-next-app. This is a blank project.

$ next build
warn  - You have enabled experimental feature(s).
warn  - Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use them at your own risk.

warn  - SWC minify beta enabled. https://nextjs.org/docs/messages/swc-minify-enabled
info  - Checking validity of types
info  - Creating an optimized production build
info  - Compiled successfully
info  - Collecting page data
[    ] info  - Generating static pages (0/3)
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Minified React error #321; visit https://reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
    at S (/home/chuck/test/wwz/node_modules/react/cjs/react.production.min.js:18:327)
    at Object.exports.useContext (/home/chuck/test/wwz/node_modules/react/cjs/react.production.min.js:22:269)
    at Head (/home/chuck/test/wwz/node_modules/next/dist/shared/lib/head.js:170:34)
    at d (/usr/lib/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
    at bb (/usr/lib/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
    at a.b.render (/usr/lib/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
    at a.b.read (/usr/lib/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
    at Object.exports.renderToString (/usr/lib/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
    at Object.renderPage (/usr/lib/node_modules/next/dist/server/render.js:736:46)
    at Object.defaultGetInitialProps (/usr/lib/node_modules/next/dist/server/render.js:368:51)
Downchuck commented 2 years ago

This was related to multiple npm library folders... Figured out when I ran "npm run dev" vs "next dev" - the latter did not work, the former did. Two things were going very wrong: my npm installation went from /usr to /usr/local as a prefix; running the "next" command was using that /usr/bin/next, and things got quite confused between the project node modules and the global installation.

Going through all of this, I still think it may be related to the issue that @imconfused218 was hitting - it's just that the error was getting caught.

morganfeeney commented 1 year ago

I'm getting this running Nextjs 13.2.4 on Azure App Service:

2023-06-21T19:18:55.186542902Z 19:18:55 0|my-nextJs-site  | ready - started server on 0.0.0.0:8080, url: http://localhost:8080
2023-06-21T19:18:55.196549942Z 19:18:55 0|my-nextJs-site  | info  - Loaded env from /home/site/wwwroot/.env.production
2023-06-21T19:19:17.938867952Z 19:19:17 0|my-nextJs-site  | Error: invariant: static responses cannot be piped. This is a bug in Next.js
2023-06-21T19:19:17.939830865Z 19:19:17 0|my-nextJs-site  |     at RenderResult.pipe (/home/site/wwwroot/node_modules/next/src/server/render-result.ts:33:13)
2023-06-21T19:19:17.940760077Z 19:19:17 0|my-nextJs-site  |     at Object.sendRenderResult (/home/site/wwwroot/node_modules/next/src/server/send-payload/index.ts:103:18)

next.config.js


module.exports = {
  reactStrictMode: true,
  images: {
    domains: [some urls are here],
  },

  async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          {
            key: "X-Frame-Options",
            value: "allow-from https://www.youtube.com",
          },
        ],
      },
    ];
  },
};

// Injected Content via Sentry Wizard Below

const { withSentryConfig } = require("@sentry/nextjs");

module.exports = withSentryConfig(
  module.exports,
  {
    // For all available options, see:
    // https://github.com/getsentry/sentry-webpack-plugin#options

    // Suppresses source map uploading logs during build
    silent: false,

    org: "macrium",
    project: "javascript-nextjs",
  },
  {
    // For all available options, see:
    // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/

    // Upload a larger set of source maps for prettier stack traces (increases build time)
    widenClientFileUpload: true,

    // Transpiles SDK to be compatible with IE11 (increases bundle size)
    transpileClientSDK: true,

    // Routes browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers (increases server load)
    tunnelRoute: "/monitoring",

    // Hides source maps from generated client bundles
    hideSourceMaps: true,

    // Automatically tree-shake Sentry logger statements to reduce bundle size
    disableLogger: true,
  }
);
rudden commented 11 months ago

We've receiving multiple errors of this kind in our logfiles. Hosted on Azure app service (linux) and running on PM2. Do we have any more information on what might be causing this? Would be nice to have more background and what it could lead to for our end users.

nikita-s-sauce commented 10 months ago

Same issue

We are using Azure App Service + Linux + PM2 and some short period of a time getting 5xx in logs: Error: invariant: static responses cannot be piped. This is a bug in Next.js . Last week it happened 38 times which is 0,03% of all requests

Using: NextJS - v13.2.1 node - v18.16.1 npm - v9.6.4

getStaticProps - with revalidate option custom server - that sends logs through pino, pino-http, pino-datadog-logger, to DataDog

4leite commented 2 months ago

@nikita-s-sauce Did you find any resolution for this?

We are also seeing this intermittently running Azure App Service + Linux + PM2 with custom server and using a revalidate end point, so it seems a similar stack.