next.js: [NEXT-1119] Socket.IO Not working anymore from Next.js 13.2.5-canary.27 to latest Next.js 13.4.1

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.4.0: Mon Mar  6 21:00:41 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T8103
    Binaries:
      Node: 18.16.0
      npm: 9.5.1
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.4.1-canary.2
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0

warn  - Latest canary version not detected, detected: "13.4.1-canary.2", newest: "13.4.1".
        Please try the latest canary version (`npm install next@canary`) to confirm the issue still exists before creating a new issue.
        Read more - https://nextjs.org/docs/messages/opening-an-issue

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/nextjs-socketio-u89y82?file=%2Fpackage.json&selection=[{"endColumn"%3A1%2C"endLineNumber"%3A4%2C"startColumn"%3A1%2C"startLineNumber"%3A4}]

To Reproduce

Agenda of this project?

  • To setup the Socket.Io server and share the information from one client to another user socket.io events

The App is have the following things -

  • An api for initialising the Socket.Io server - inside /pages/api/socketio
  • A client page to connect to this server - inside /app/page

Whats the Issue?

  • There has been an unknown error in network connection from client side when its trying to create the Socket.Io connection.

Since when this issue is happening?

  • This has been happening from Next.js version 13.2.5-canary.27 version and its still happening even in latest canary release 13.4.1-canary.2 and also the latest release Next.js 13.4.1

Do we have an Example project?

  • Yes, I have created a testing project in codesandbox, that I have already shared. (Link)

Steps to Reproduce

  • Just see the console and network tabs for the client connection error. It will happen to all the versions on and above 13.2.5-canary.27
  • And to see if its fixed, you need to downgrade to 13.2.5-canary.26

Some References PR for / might this issue have created?

  • I some how gathered the PR for the version when this Socket.Io broken (i.e. 13.2.5-canary.27) - See here

Describe the Bug

  • There has been an unknown error in network connection from client side when its trying to create the Socket.Io connection.

Expected Behavior

  • There should be successful Socket.Io connection.
  • It should exactly work the same way as it was working 13.2.5-canary.26 or lower.
  • I was using 13.2.4 as stable version for our production application, as we had to use Socket.Io for websocket connection.

Which browser are you using? (if relevant)

I am using latest Chrome version, but this has to do more with Next.js Core server. It has nothing to do with any browsers.

How are you deploying your application? (if relevant)

Using Docker, but this is irrelevant too, as in localhost also, there is this issue.

NEXT-1119

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 81
  • Comments: 100 (8 by maintainers)

Commits related to this issue

Most upvoted comments

It appears that after “13.2.5-canary.26”, a trailing slash is appended to the end of the route.

Disabling “addTrailingSlash” in the Socket.IO Server constructor resolved this for me on the latest version (13.4.1).

"pages/api/socket.js"

const io = new Server(res.socket.server, {
   path: "/api/socket_io",
   addTrailingSlash: false
 });

Thank you for reporting! The best way to track this is by upvoting the issue versus commenting, unless you can provide additional information or reproductions. Greatly appreciate the assistance with making a minimal reproduction 🙏

Issue still persists in next@13.5.5. I’m not using socket.io, just plain ws. Getting instant disconnects. We are all stuck in next@13.4.12 which is 3 months old and has security issues within dependencies.

Is there a chance to increase priority on this?

Module not found: Can’t resolve ‘bufferutil’ in … Module not found: Can’t resolve ‘utf-8-validate’ in

npm install bufferutil utf-8-validate

For anyone encountering this, I added the following to my next.config.js:

/** @type {import('next').NextConfig} */

const nextConfig = {
  webpack: (config) => {

    config.externals.push({
      'utf-8-validate': 'commonjs utf-8-validate',
      bufferutil: 'commonjs bufferutil',
    })

    return config
  },
}

module.exports = nextConfig

which resolved it for me

The fix is landed in 14.0, please upgrade to the latest next.js! 🙏 btw there’s no new feature so it should work well like v13

This is brutal and blocking me from using Vercel / Next.js as a fullstack backend for apps… I think we deserve a full Websockets docs section inside API Route Handlers v13.

Currently using v13.2.4 and old /pages just to get sockets to work.

S.O.S.

Anyone can update code for app/api not pages/api ?

13.4.4 here. Any resolution to this? REALLY need socket.io… I refuse to fall back to standard polling 🤦

I’m meeting this problem too when upgrading Next.js to 13.5.4

Hoping the issue can be resolved soon.

Our teams are currently thinking of migrating our existing applications (express/psql/sio stack) to Next 13 and benefiting from the new stable App Router API, but this Socket.IO issue is an absolute no-go for the moment. We really need a solution for this issue, and we also need to be able to bind the sio handler to the main server.

It appears that after “13.2.5-canary.26”, a trailing slash is appended to the end of the route.

Disabling “addTrailingSlash” in the Socket.IO Server constructor resolved this for me on the latest version (13.4.1).

"pages/api/socket.js"

const io = new Server(res.socket.server, {
   path: "/api/socket_io",
   addTrailingSlash: false
 });

This worked for me

We landed a fix in #54813 that will fix this issue. Testing against next.js version ^13.4.20-canary.24 works for me with the original reproduction. Please uprgade to the new version, thanks!

image

I can make it work by following code on following version

"socket.io": "^4.7.1",
"socket.io-client": "^4.7.1",
"next": "13.4.7",

on “use client” side app/chat/page.tsx

import { io as ClientIO } from 'socket.io-client';
...

  useEffect((): any => {
    const socket = new (ClientIO as any)(process.env.NEXT_PUBLIC_SITE_URL, {
      path: '/api/socket',
      addTrailingSlash: false
    });

on api side pages/api/socket.ts

import { Server as ServerIO } from 'socket.io';
...
export default async (req: NextApiRequest, res: NextApiResponseServerIO) => {
  if (!res.socket.server.io) {
    console.log('New Socket.io server...');
    // adapt Next's net Server to http Server
    const httpServer: NetServer = res.socket.server as any;
    const io = new ServerIO(httpServer, {
      path: '/api/socket',
      addTrailingSlash: false
    });
    // append SocketIO server to Next.js socket server response
    res.socket.server.io = io;
  }
  res.end();
};

full source code here https://github.com/danya0365/nextjs13-realtime-chat-with-socketio

Any solution for pure app dir work? Currently my working approach is api is from pages dir and website is from app dir.

any solutions ? : (using App Router)

‘use client’ import { useEffect, useState } from ‘react’; import io from ‘socket.io-client’;/////this line is producing the error

const socket = io(‘http://localhost:3000’);

export default function Page(){ const [newDecision, setNewDecision] = useState(‘’); useEffect(() => { socket.on(‘newDecision’, ({ decision }) => { setNewDecision(decision);} }); }, []);

return (<div></div> ); };

errors :

Module not found: Can’t resolve ‘bufferutil’ in … Module not found: Can’t resolve ‘utf-8-validate’ in

I think this is getting no love because Vercel is pushing for “Server Actions” now… imo Server Actions are not as performant as real WebSocket and game devs need a real socket for multiplayer experiences.

Definitely not the reason at all, there’s hundreds of open issues and this one has been triaged and put into our issue tracker, it’s just that we haven’t gotten around to investigating this further.

Downgraded my NextJS version to 13.2.4 to resolve the issue temporarily.

The problem still remains and is about Next.js server ignores listeners to upgrade event of Next.js server from Next.js 13.3.

https://codesandbox.io/p/sandbox/busy-euclid-qbvdv8

This project creates an API route (pages/api/proxy.ts) that adds a listener to next.js server listening to upgrade event when accessed and prints a setup upgrade log. The listener just logs a upgrade log to indicate the upgrade event is handled. There is also a page (apps/page.tsx) that first calls the API route (to register the listener), and then tries to establish a WS connection to the server.

In Next.js 13.2.5, it works fine. Both setup upgrade and upgrade logs are printed.

image

In Next.js 13.4.2, only setup upgrade log is printed. It means the server.on("upgrade", {handler} is called, but the listener is ignored.

image

For socket.io, I’m seeing the errors of missing errors of packages bufferutil and utf-8-validate, and when I installed then I can see the connection become normal.

From socket.io docs it also mentioned to install them as dependency

It appears that after “13.2.5-canary.26”, a trailing slash is appended to the end of the route.

Disabling “addTrailingSlash” in the Socket.IO Server constructor resolved this for me on the latest version (13.4.1).

"pages/api/socket.js"

const io = new Server(res.socket.server, {
   path: "/api/socket_io",
   addTrailingSlash: false
 });

Thank you for this update, this has resolved the network issue we got earlier, but still the WS connection is not working like earlier, it always stays in pending mode image

You can please check and confirm that its working when you switch back to old version of Next.js

Thank you for the patch! In my case, after upgrade to next@14.0.0 I’m still facing the same issue.

Same issue. Downgraded to 13.4.12 like @RonaldErnst suggested and it works fine…

Hope we can get this resolved quickly.

Websockets are completely broken on nextJS, across all libraries. I need to force websocket transport with socket.io to deploy to cloud run. Alternative socket.io transports seem to work but I need websockets…

Another temp fix could be deploying WS server to a different port but once again that wouldn’t work for people using cloud run etc…

It appears that after “13.2.5-canary.26”, a trailing slash is appended to the end of the route.

Disabling “addTrailingSlash” in the Socket.IO Server constructor resolved this for me on the latest version (13.4.1).

"pages/api/socket.js"

const io = new Server(res.socket.server, {
   path: "/api/socket_io",
   addTrailingSlash: false
 });

Can make the code for app/api ?

I confirm its working perfectly fine with Next.js Latest version (14.0.0), however one must ensure to use Node v18.17.x or higher version, as its a breaking change in Next.js 14 - refer the changelog for Next.js v14 here.

Thank a lot @huozhi, @shuding and the Next.js team for resolving this issue. Also I thank you very much @leerob for helping me to create this issue page for the resolution. Lots of ❤️ for the great Next.js Community.

Still getting Websocket closed prematurely and Websocket is already in CLOSING or CLOSED state on next@13.5.7-canary.37 and next@14.0.0 using a custom server and the ws library.

I am having the same problems even without socket io. I’m using t3-stack with trpc’s websocket implementation and the server is getting flooded with upgrade requests that close down with 1006 error immediately after.

I believe this is a general websocket problem since other libraries are having the same issue #54589 . Latest working version for me is next@13.4.12.

@huozhi I just realised that the socket.io is falling back to polling instead of WebSocket. Can you check on this once? You can check that if you switch latest 13.5.4 with 13.2.4 it works with WebSocket.

Codesandbox testing project - https://codesandbox.io/p/sandbox/nextjs-socketio-forked-7k5px3?file=%2Fpackage.json%3A4%2C21&selection=[{"endColumn"%3A1%2C"endLineNumber"%3A4%2C"startColumn"%3A1%2C"startLineNumber"%3A4}]

I found that (on a custom Express server also), when Webpack HMR WebSocket connects, Socket.IO doesn’t connect. If you try to create a separate index.html file and connect it to the same Socket.IO server, it works. However, if you open any Next.js page (which will automatically connect Webpack HMR), after that, the WebSocket in index.html also stops working.

I ended up using a separate port, and it’s working in production as well.

//page/api/socket.ts

const io = new Server({ path: "/api/socket", addTrailingSlash: false, cors: { origin: "*" } }).listen(PORT + 1)
//socketClient.ts

const socket = io(`:${PORT + 1}`, { path: "/api/socket", addTrailingSlash: false })
socket.on("connect_error", async err => {
   console.log(`connect_error due to ${err.message}`)
   await fetch("/api/socket")
 })

I wasn’t sure if this would work on Vercel, but it’s working with separate deployments.

"next": "^13.5.1",
"socket.io": "^4.7.2",
"socket.io-client": "^4.7.2"

@huozhi i tested it now in production and it is not working there.

It works in dev-env where i need to start a custom ws-server to not collide with webpack HMR. In production i did not need this extra server and can reuse the original custom http server. But it seems like it does not work anymore.

We landed a fix in #54813 that will fix this issue. Testing against next.js version ^13.4.20-canary.24 works for me with the original reproduction. Please uprgade to the new version, thanks!

image

This fix seems to still have issues; while it can connect via HTTP polling or websocket, if you connect via polling (default), it cannot upgrade to websocket successfully.

See my fork of the original sandbox, where I added a upgrade event handler: https://codesandbox.io/p/sandbox/nextjs-socketio-forked-39xjkv?file=/app/page.jsx:1,1

Guess I’ll file a new bug ticket?

@danya0365 apporach for me works but not on production. What i had to do was stop using nextjs custom servers and instead convert my socketio nextjs api route code to a local node app and it works fine on production too. only hastle is i have to deploy the node server too but its fine.

I dont want to add more fuel to the fire, but downgrading to 13.2.4 seems to work localhost. as soon as I deploy to vercel I get those 404’s

@danya0365 The method you’ve explained works but it uses Http/s Polling and Not WebSocket. The whole point to use socket.io is for using WebSocket messaging.

I have solved the issue by using custom server. It is possible to bind the http.Server object to req.socket and access the object from API route, where upgrade event can be bound to handle WS connections.

// server/index.ts
// ...
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

async function main() {

  await app.prepare();

  // create our own http.Server object.
  const server = createServer(async (req, res) => {

    // bind the http.Server object before using next.js to handle the request
    (req.socket as any).server = server;
    await handle(req, res);
  });

  // ...
}

It requires an extra build step that builds every source file after next build, and the files from both build steps(.next and the output dir of this extra build) must be distributed to run the server.

The issue still persists on version 13.4.19 In my case the socket seems like it made the connection but drops off immediately and tries to reconnect.

I ended up downgrading to v13.2.4

Hoping for a solution in the next updates 🙏🏻

i can confirm: it is working for my setup and app with 13.4.20-canary.24|25

👋🏻 Socket.io’s websocket server monitors connected clients on port 8888, and can initiate an immediate action upon any modification of the database, thereby forcing real-time modification on the active clients’ interface.

Corresponding to security policy (CORS) and allowed “origins” in the development environment is enabled as “*”; in a production environment, the websocket server will be activated by specifying the “withCredentials: true” and the “custom-header” information created in the next phase of development. The data set emitted by the client contains the value of the “custom-header” and is used to identify the clients accordingly, thereby preventing the successful connection of “uninvited” clients who inquire via websockets, even malicious ones.

The Socket.io server is continuously activated - once - during the Next.js application “compile” according to the environment variables that can be used in the .env file; when the web application is opened for the first time, the clients check the active status of the websocket server with an asynchronous XHR query and continue to function depending on the status returned as a response. In the case of an active status, the next step is to communicate depending on the authenticated status of the user - it waits and processes received data, - the connected client. (This is where the distinguished “custom-header” is of great importance!)

Here are some screenshots as proof:

kép

kép

kép

On cloud hosting platforms like Vercel and Heroku the above mentioned configs and the correct settings of the environment variables and the corresponding CSP settings must to be configured well to get functional WebSocket communication!

I hope it will helpful for you guys! 🙂

I think this is getting no love because Vercel is pushing for “Server Actions” now… imo Server Actions are not as performant as real WebSocket and game devs need a real socket for multiplayer experiences.

@danya0365 It works for app directory. MHR and socket all works.

are there any solutions for app directory? 😭

You can do one thing, You can make your app in app directory but just for socket to work make an api under pages directory.

are there any solutions for app directory? 😭

Về version 13.2.4 là dùng được nhé ông. Tôi dùng được rồi nhưng không global socket được.

GET http://localhost:3000/api/socket_io?EIO=4&transport=polling&t=OXIVwM_ 404 (Not Found)

For those who are having this 404 error, I found that removing not-found.jsx file fixes this.

Module not found: Can’t resolve ‘bufferutil’ in … Module not found: Can’t resolve ‘utf-8-validate’ in

npm install bufferutil utf-8-validate

It appears that after “13.2.5-canary.26”, a trailing slash is appended to the end of the route. Disabling “addTrailingSlash” in the Socket.IO Server constructor resolved this for me on the latest version (13.4.1).

"pages/api/socket.js"

const io = new Server(res.socket.server, {
   path: "/api/socket_io",
   addTrailingSlash: false
 });

Thank you for this update, this has resolved the network issue we got earlier, but still the WS connection is not working like earlier, it always stays in pending mode image

You can please check and confirm that its working when you switch back to old version of Next.js

your code is working now please follow this : in socket.js add: const io = new Server(res.socket.server, { path: ‘/api/socket_io’, addTrailingSlash: false, });

in page.jsx : socket = io(undefined, { path: ‘/api/socket_io’, });

and update all packages  

1 2 3