Hello Vercel Community,
Could you please help for the issue i am facing? when i deploy bun express project to Vercel.
Steps i did before creating this topic:
- I have read this doc
- FUNCTION_INVOCATION_FAILED
- it just says to check logs and nothing helpful.
- FUNCTION_INVOCATION_FAILED
- I have read topics suggested
- Hono Node runtime won’t deploy on vercel - Help - Vercel Community
- the above is not related because my error is This Serverless Function has crashed.
- ERROR in deploying my Astro/react firebase authentic and firestore project - Help - Vercel Community
- no solution provided.
- Hono Node runtime won’t deploy on vercel - Help - Vercel Community
Current behavior
The deployment builds successfully, but the Serverless Function crashes at runtime when a React TSX SSR route is introduced.
Visiting the deployed URL results in:
This Serverless Function has crashed.
500: INTERNAL_SERVER_ERROR
Code: FUNCTION_INVOCATION_FAILED
ID: bom1:bom1::795sp-1766311001732-983203ba7892
Deployment URL:
ecom-api-12a876as1-dy1-projects.vercel.app
The same code works perfectly locally using Bun.
If I remove the TSX / React SSR code and revert to static .htm files, the deployment works again.
Expected behavior
- React SSR using
.tsxshould work in a Bun + Express serverless function - Or at least fail at build-time with a clear error
- The function should not crash at runtime after a successful build
Runtime error logs (Serverless Function)
2025-12-21 09:56:43.756 [error] TypeError: Requested module is not instantiated yet.
at link (native:1:11)
at link (native:1:11)
at link (native:1:11)
at linkAndEvaluateModule (native:1:11)
at requestImportModule (native:2)
at processTicksAndRejections (native:7:39)
Bun process exited with exit status: 1.
The logs above can help with debugging the issue.
This error happens only when TSX + React SSR is used.
Build logs (successful)
Running "vercel build"
Vercel CLI 50.1.3
Installing dependencies...
bun install v1.3.4
* react@19.2.3
* react-dom@19.2.3
* @types/react@19.2.7
* @types/react-dom@19.2.3
Running "bun run build"
$ tsc --noEmit
Using TypeScript 5.8.3
Build Completed
Deployment completed successfully
So:
- Build passes
- TypeScript passes
- Crash happens only at runtime
Code file index.ts
import { OpenAPIHandler } from "@orpc/openapi/node";
import { onError } from "@orpc/server";
import { apiReference } from "@scalar/express-api-reference";
import cookieParser from "cookie-parser";
import cors from "cors";
import express, { NextFunction, Request, Response } from "express";
import { connectDB } from "./lib/mongo.js";
import { apiRateLimit, openApiAccess, serverGate } from "./middleware/index.js";
import { generateOpenAPISpec } from "./orpc/openapi.js";
import { orpcRouter } from "./orpc/router.js";
import { aboutRouter, healthzRouter, homeRouter, loginRouter } from "./routes/index.js";
const app = express();
// ===============================================
// Core middleware
// ===============================================
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// ===============================================
// Database connection
// ===============================================
app.use(async (_req, res, next) => {
try {
await connectDB();
next();
} catch (err: unknown) {
console.error("DB init failed:", err);
res.status(503).json({
success: false,
status: 503,
message: "Database unavailable",
});
}
});
// ===============================================
// CORS
// ===============================================
app.use(
cors({
origin: [
"https://r9k0j6rn-3000.inc1.devtunnels.ms",
"http://localhost:3000",
],
credentials: true,
allowedHeaders: [
"Content-Type",
"Authorization",
"X-Client-Id",
"X-Client-Secret",
],
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
optionsSuccessStatus: 204,
})
);
// ===============================================
// Static assets
// ===============================================
app.use(express.static("public"));
// ===============================================
// Rate limit
// ===============================================
app.set("trust proxy", 1);
app.use("/api", apiRateLimit);
// ===============================================
// Docs login (ONLY public thing)
// ===============================================
app.use("/login", loginRouter);
// ===============================================
// GLOBAL SERVER GATE (ABSOLUTE)
// ===============================================
app.use((req, res, next) => {
// 1. Internal Next.js frontend → always allowed
if (serverGate(req)) {
return next();
}
// 2. Allow login page itself (avoid infinite redirect)
if (req.path.startsWith("/login")) {
return next();
}
// 3. Logged-in browser (cookie)
if (req.cookies?.auth === "ok") {
return next();
}
// 4. EVERYTHING ELSE → redirect to login
return res.redirect("/login");
});
// ===============================================
// OpenAPI JSON (PROTECTED)
// ===============================================
app.get("/api/openapi.json", openApiAccess, async (_req, res) => {
const spec = await generateOpenAPISpec();
res.json(spec);
});
// ===============================================
// API Docs (Scalar UI) — PROTECTED
// ===============================================
app.use(
"/api/docs",
apiReference({
url: "/api/openapi.json",
})
);
// ===============================================
// HTML routes (PROTECTED)
// ===============================================
app.use("/", homeRouter);
app.use("/about", aboutRouter);
// ===============================================
// Health check (PROTECTED)
// ===============================================
app.use("/healthz", healthzRouter);
// ===============================================
// oRPC REST handler (PROTECTED)
// ===============================================
const orpcHandler = new OpenAPIHandler(orpcRouter, {
interceptors: [
onError((_error: unknown) => {
// optional logging
// console.error("[oRPC error]", error);
}),
],
});
app.use(async (req, res, next) => {
const result = await orpcHandler.handle(req, res, {
// prefix: "/api",
context: {
headers: req.headers,
},
});
if (result.matched) {
return;
}
next();
});
// ===============================================
// Global error handler
// ===============================================
app.use((err: unknown, req: Request, res: Response, _next: NextFunction) => {
const msg = err instanceof Error ? err.stack : 'Something went wrong!';
console.error(`Global Error - ${msg}`);
res.status(500).json({
success: false,
statusCode: 500,
error: "Something went wrong",
});
});
export default app;
Code that triggers the issue (login route only)
src/routes/login.tsx
import type { Request, Response } from "express";
import { Router } from "express";
import { Lock, User } from "lucide-react";
import React from "react";
import { renderToString } from "react-dom/server";
const router = Router();
type Props = {
title: string;
};
function Login({ title }: Props): React.ReactElement {
return (
<html lang="en">
<head>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{title}</title>
<link rel="stylesheet" href="/style.css" />
<link rel="stylesheet" href="/login.css" />
</head>
<body>
<div className="login-body">
<div className="login-container">
<h2>Ecom Server API Login</h2>
<form method="POST">
<div>
<User />
<input name="username" placeholder="Username" required />
</div>
<div>
<Lock />
<input
name="password"
type="password"
placeholder="Password"
required
/>
</div>
<button type="submit">Sign In</button>
</form>
</div>
</div>
</body>
</html>
);
}
router.get("/", async (_req: Request, res: Response) => {
const html = renderToString(<Login title="Login | Ecom API Hub" />);
return res.type("html").send("<!DOCTYPE html>" + html);
});
export default router;
Configuration
vercel.json
{
"bunVersion": "1.x"
}
package.json (relevant parts)
{
"type": "module",
"scripts": {
"build": "tsc --noEmit"
},
"dependencies": {
"express": "^5.2.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"lucide-react": "^0.562.0"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"jsx": "react-jsx",
"module": "NodeNext",
"types": ["bun"],
"skipLibCheck": true
}
}
Notes / Observations
- The app is a pure Express server, not Next.js
appis exported correctly fromsrc/index.ts- The serverless function is detected correctly (
runtime: bun1.x) - The crash happens only when importing React / TSX - i believe.
- Local Bun runtime works fine with the same code
Questions
-
Is React SSR with TSX officially supported in Bun-based Vercel Serverless Functions?
-
Is a manual prebuild step (TSX → JS) required for this setup? I dont know how, need help.
-
What causes the runtime error:
TypeError: Requested module is not instantiated yetin this context?
-
Is this a known limitation of:
- Bun runtime on Vercel?
- React 19 with SSR?
- ESM + NodeNext in serverless functions?
Any guidance or confirmation would be very helpful.
Thanks!
Regards
Dheeraj