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_ERRORCode: FUNCTION_INVOCATION_FAILEDID: 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 --noEmitUsing TypeScript 5.8.3
Build CompletedDeployment 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