Vercel says 500: INTERNAL_SERVER_ERROR, FUNCTION_INVOCATION_FAILED
You built an app with v0, Lovable, Bolt, Cursor, or Replit, deployed it to Vercel, and now some page or API call shows a plain error screen: 500: INTERNAL_SERVER_ERROR, Code: FUNCTION_INVOCATION_FAILED, sometimes with the line "This Serverless Function has crashed." That screen means your server-side code threw an error. It tells you nothing about why, on purpose, so visitors do not see your internals. The why is sitting in a log almost nobody knows exists. Start there, then check the six causes below. Each check takes about two minutes.
Step 0: read the actual crash reason in the logs
Vercel records the real error message and stack trace for every crash. A stack trace is the list of lines that shows exactly what failed and where. To see it:
- Go to
vercel.com, log in, and click your project. - Click the Logs tab in the top navigation (on some views it is under Observability, then Logs).
- Reload the broken page on your live site so a fresh crash gets logged, then look for a red row marked 500 or Error.
- Click the row. The panel that opens shows the message, something like
Error: STRIPE_SECRET_KEY is not definedorCannot find module 'fs', plus the file and line it came from.
That message usually points straight at one of the causes below. If you paste it into the free diagnosis form at the bottom of this page, it is often enough to name the fix outright.
Cause 1: a server-side env var exists locally but not on Vercel
This is the number one cause. Secret keys like STRIPE_SECRET_KEY, DATABASE_URL, SUPABASE_SERVICE_ROLE_KEY, or OPENAI_API_KEY live in your local .env file, and .env is gitignored, so Vercel never got them. Server code reads undefined, then crashes the moment it tries to use the value. Note these are the vars without a NEXT_PUBLIC_ prefix; a missing public var breaks the browser side, but a missing secret one crashes the function itself.
- In the Vercel dashboard: your project, then Settings, then Environment Variables.
- Compare that list against your local
.envfile line by line. Add every missing one, exact same name, for the Production environment (and Preview if you use preview deploys). - Redeploy. Env vars are read at deploy time. Go to the Deployments tab, open the latest deployment's three-dot menu, and click Redeploy. Adding a var without redeploying changes nothing, which explains most "I added it and it still 500s" threads.
Cause 2: every single route 500s at once
If literally the whole app is down, not just one page, some file is crashing at import time: code that runs the moment the file loads, before any request is handled. The classic is an AI-generated client that throws when its env var is missing, like new Stripe(process.env.STRIPE_SECRET_KEY) or a Supabase admin client created at the top of a shared file. One missing var, and every route that touches that file dies on cold start. The log from Step 0 will show the throw happening at the top of a file, not inside a request handler. Fix the env var per Cause 1, or move the client creation inside the function that uses it so only that route depends on it.
Cause 3: wrong runtime, or Node-only code on the Edge
Vercel functions run in one of two environments: the full Node.js runtime, or the lighter Edge runtime. Edge is fast but cannot use Node APIs like fs (reading files), path, native modules, or many database drivers. AI tools sometimes emit export const runtime = 'edge' or an Edge middleware that imports Node-only code, and the log shows errors like Cannot find module 'fs' or a webpack "not supported in the Edge Runtime" message. To check: search your code for runtime = 'edge' or runtime: 'edge'. If the crashing file has it and imports anything Node flavored, change it to export const runtime = 'nodejs' and redeploy. Also, writing files to disk does not work on serverless at all except in /tmp, and even that vanishes between requests.
Cause 4: the timeout variant, FUNCTION_INVOCATION_TIMEOUT
If your error code says FUNCTION_INVOCATION_TIMEOUT instead, the function did not crash, it ran out of time. The Hobby (free) plan cuts functions off around 10 seconds by default. Three usual suspects: a database that is slow to wake up (see Cause 6), a missing await so the function waits on something that never resolves, or an accidental infinite loop or retry storm in generated code. The log timestamps in Step 0 show how long the invocation ran. If it always dies right at the limit, find the slow call, or raise maxDuration in the route file or vercel.json (paid plans allow more).
Cause 5: the database is unreachable from Vercel
Works on your laptop, 500s in production, and the log mentions ECONNREFUSED, ETIMEDOUT, or "too many connections"? Two separate problems hide here:
- The free tier database is paused. Supabase pauses free projects after about a week idle; Neon suspends after minutes. Open your database dashboard, look for a paused banner, click restore or just run a query to wake it, then retry your app. The first request after waking can also be slow enough to trip Cause 4.
- You are using the direct connection string instead of the pooled one. Serverless spins up many short-lived copies of your function, and each one opening its own database connection exhausts the limit fast. Supabase: use the pooler string from Connect in your project dashboard, the one on port
6543(pgbouncer), not5432. Neon: use the connection string whose host contains-pooler. Put the pooled string inDATABASE_URLon Vercel and redeploy.
Cause 6: it deployed fine before, and you changed nothing
Then something external changed: a free database got paused (Cause 5), an API key was rotated or expired, a third-party service you call is down, or a dependency update came in through a fresh build. The log from Step 0 names the failing call. Quick isolation trick: in the Deployments tab, find the last deployment that worked and click Promote to Production (or "Instant Rollback"). If the old build fails too, the problem is external, almost always a paused database or dead key, not your code.
Still stuck?
Run the instant diagnosis. Paste your public repo URL into the form and an automated clean-room check reports what is broken: install, build, missing env config, and render, with the exact blocker named, in minutes, free. It catches the missing env var and import-crash cases directly. Runtime-only failures live in your Vercel logs rather than the repo, so also paste the error message and stack trace from Step 0 (strip out any secret values) into the issue and I will look the same day. Private repo or zip? Email works too.
Get an instant free diagnosisOr email me instead. Fixes with 24 hour turnaround start at $95. Prefer self-serve? The $5 instant diagnosis on Apify checks your repo privately, no public issue needed.