-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
TypeError: handler is not a function before server is fully online #49536
Comments
The issue appears to have been introduced here: 83b774e where the creation of the Next Server now returns a promise that takes a while to resolve |
that's interesting, that also might be source of my prisma issues |
Here is a server.js that works if it helps you: const http = require("http");
const path = require("path");
const {
createServerHandler,
} = require("next/dist/server/lib/render-server-standalone");
const dir = path.join(__dirname);
process.env.NODE_ENV = "production";
process.chdir(__dirname);
// Make sure commands gracefully respect termination signals (e.g. from Docker)
// Allow the graceful termination to be manually configurable
if (!process.env.NEXT_MANUAL_SIG_HANDLE) {
process.on("SIGTERM", () => process.exit(0));
process.on("SIGINT", () => process.exit(0));
}
const currentPort = parseInt(process.env.PORT, 10) || 3000;
const hostname = process.env.HOSTNAME || "localhost";
const keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10);
// const nextConfig = {}; // ommitted for brevity
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig);
createServerHandler({
port: currentPort,
hostname,
dir,
conf: nextConfig,
}).then((nextHandler) => {
console.log("Creating http server");
const server = http.createServer(async (req, res) => {
try {
console.log("Handling request");
await nextHandler(req, res);
} catch (err) {
console.error("Failed to call handler", err);
res.statusCode = 500;
res.end("Internal Server Error");
}
});
if (
!Number.isNaN(keepAliveTimeout) &&
Number.isFinite(keepAliveTimeout) &&
keepAliveTimeout >= 0
) {
console.log("Setting keep alive timeout", keepAliveTimeout);
server.keepAliveTimeout = keepAliveTimeout;
}
server.listen(currentPort, async (err) => {
if (err) {
console.error("Failed to start server", err);
process.exit(1);
}
console.log(
"Listening on port",
currentPort,
"url: http://" + hostname + ":" + currentPort
);
});
}).catch(err => {
console.error("Failed to create next server handler", err);
process.exit(1);
}); You can copy it manually to the standalone directory to override the one Next.js generates after running a build:
|
…t handler is ready (#49548) ### Fixing a bug Fixes #49536 Fixes #49338 ### What? Starting on next.js 13.4.0, the `server.js` file created by the standalone output is incorrect because it does not wait until the Next handler is ready before node http server starts accepting requests. Initial requests will produce the following error: ``` TypeError: handler is not a function at Server.<anonymous> (/tmp/app/server.js:29:11) at Server.emit (node:events:513:28) at parserOnIncoming (node:_http_server:998:12) at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17) ``` ### Why? The creation of the next server takes roughly 800ms on a basic hello world app which causes the initial requests to fail because the `handler` variable is not initialized. ### Solution This changes the order of code so that Next Server is initialized before the Node HTTP server and awaits until the promise is completed to kick off the HTTP server. ### Alternative code ```js let handler; const server = http.createServer(async (req, res) => { try { await waitUntilHandlerIsReady(); // <---- wait here await handler(req, res); } catch (err) { console.error("Failed to call handler", err); res.statusCode = 500; res.end("Internal Server Error"); } }); async function waitUntilHandlerIsReady() { if (!handler) { await new Promise((resolve) => setTimeout(resolve, 200)); await waitUntilHandlerIsReady(); } } ``` --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl> Co-authored-by: JJ Kasper <jj@jjsweb.site>
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Verify canary release
Provide environment information
Operating System: Platform: linux Arch: x64 Version: #1 SMP Tue Sep 13 07:51:46 UTC 2022 Binaries: Node: 20.1.0 npm: 9.6.4 Yarn: 1.22.19 pnpm: N/A Relevant packages: next: 13.4.1 eslint-config-next: 13.4.1 react: 18.2.0 react-dom: 18.2.0
Which area(s) of Next.js are affected? (leave empty if unsure)
To Reproduce
I'm building the app for docker in standalone mode, so I start the server with
node server.js
.I'm also deploying in kubernetes, and this is happening. at the moment it's unclear if it's happening because traffic is hitting the pod before the server is fully ready or there's something else.
Describe the Bug
Expected Behavior
I'm debugging an issue with prisma connections and stumbled upon this, so I took a look at the compiled server.js
maybe to ensure the server is fully initialized before it starts accepting incoming traffic, we can move the
handler
initialization to be before thecreateServer
call, like this?Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
The text was updated successfully, but these errors were encountered: