Skip to main content
友田 陽大
Vercel in production
Vercel
Next.js
可観測性
インフラ
CI/CD
TypeScript
パフォーマンス

The complete Vercel troubleshooting compendium: crushing build failures, function errors, 504/413, 404, and cold starts by cause

A practical guide to resolving common Vercel production errors by cause. It explains, with real code and faithful to the official docs: FUNCTION_INVOCATION_TIMEOUT(504), FUNCTION_PAYLOAD_TOO_LARGE(413), FALLBACK_BODY_TOO_LARGE, build failures (output directory/build script/function pattern/config conflict), dynamic-route 404s, environment variables not taking effect, cold starts, and Edge Config connection errors — the causes and fix procedures.

Published
Reading time
7 min read
Author
友田 陽大
Share

When a 504, 413, or build failure appears in production, you panic. But Vercel errors have mostly fixed categories and causes, so you can crush them quickly with a reverse look-up. This article, faithful to Vercel's official error list and Functions limitations, is a practical collection organizing the errors that really appear in the field, by cause.

For the big picture, see the Vercel production-operations guide.


First: pinpoint the symptom (don't guess)

When you see an error code, before fixing blindly, take primary-source information from the logs.

  1. Observability tab: pinpoint which route is raising the error rate/latency (observability).
  2. Runtime Logs: check the relevant function's logs and stack trace.
  3. Build Logs: build failures all appear here.
  4. x-vercel-cache / response headers: the state of caching and routing.

Errors fall into roughly 5 categories.

CategoryRepresentative codeWhere it appears
FunctionFUNCTION_INVOCATION_TIMEOUT(504), FUNCTION_PAYLOAD_TOO_LARGE(413), FUNCTION_INVOCATION_FAILED(500)At runtime
Deployment/buildMissing public directory, Missing build script, FALLBACK_BODY_TOO_LARGEAt build time
RoutingDynamic-route 404, Invalid route source patternAt request time
RequestBody overrun, auth/protectionAt the entrance
Configurationfunctions vs builds conflict, invalid Edge Config connection stringAt deploy time

Function errors

FUNCTION_INVOCATION_TIMEOUT (504)

Cause: the function didn't complete within maxDuration (default 300s, Pro/Ent max 800s). Typical of long synchronous processing, infinite waits, or external-API hangs.

Fix:

// ① まず maxDuration を用途に合わせて明示(だらだら生かさない)
export const maxDuration = 60;

// ② 長時間処理は関数に抱えず Workflows / キューへ分離
//    (数分を超える処理を同期HTTPで持たない)
export async function POST(request: Request) {
  const job = await enqueueHeavyJob(await request.json()); // すぐ返す
  return Response.json({ jobId: job.id }, { status: 202 });
}

// ③ 進捗を返したいならストリーミングで初動を速く

Attach a timeout and AbortController to external API calls to cut hangs yourself. For separating heavy processing, see the Functions guide.

FUNCTION_PAYLOAD_TOO_LARGE (413)

Cause: the request body or response body exceeded 4.5MB. Typical of receiving file uploads in a function.

Fix: send uploads directly to Vercel Blob (client upload), bypassing the function.

// 旧:関数で multipart を受ける → 4.5MB で死ぬ
// 新:client upload でブラウザから Blob へ直接(転送課金も回避)
import { upload } from "@vercel/blob/client";
const blob = await upload(file.name, file, {
  access: "public",
  handleUploadUrl: "/api/upload", // トークン発行+認可だけサーバーで
});

Details in the storage/Blob guide. For a large response, change to paging, streaming, or delivery via Blob.

FALLBACK_BODY_TOO_LARGE (ISR page too large)

Cause: when an ISR/prerender response exceeds 20MB, the page doesn't render in production. Caused by huge embedded data, inline images, or redundant JSON.

Fix: make the page output lighter. Fetch data in splits / lazy-load, externalize images with next/image, and trim unnecessary inline JSON.

FUNCTION_INVOCATION_FAILED (500)

Cause: an uncaught exception inside the function. DB connection failure, unset env, null reference, etc.

Fix: check the stack trace in Runtime Logs. Catch exceptions at the boundary and return a meaningful error instead of a 500. Since unset env is common, validate required env with Zod at startup.


Build failures

For build failures, the cause all appears in Build Logs. Frequent ones, by cause.

Wrong output directory / build script

Missing public directory / Missing build script

Cause: the output directory is wrong, there's no build script, or the root directory (monorepo) is misspecified.

Fix:

  • Check Output Directory / Build Command / Root Directory in Project Settings.
  • Run the same build command locally and confirm the artifact is generated in the output location (the fastest isolation).
  • For a monorepo, set Root Directory to the app's path.

Function pattern mismatch / config conflict

Unmatched function pattern / Conflicting functions and builds

Cause: the functions glob in vercel.json doesn't match files under api/, or you're using functions and builds together (not allowed).

Fix:

// ❌ api/ 外を指している
{ "functions": { "users/**/*.js": { "maxDuration": 30 } } }

// ✅ api/ 配下を指す(Next.js は pages/api/** も可)
{ "functions": { "api/users/**/*.js": { "maxDuration": 30 } } }

Use only one of functions or builds. As a rule, use functions (which allows memory settings, etc.). In Next.js, what you can set in functions is only memory and maxDuration (the rest is auto-managed by Next.js).

Route syntax error

Invalid route source pattern

Cause: source/rewrites/redirects in vercel.json are path-to-regexp syntax, not raw regex. A negative lookahead must be wrapped in a group.

// ❌ "source": "/feedback/(?!general)"
// ✅ "source": "/feedback/((?!general).*)"

Dependency/package-manager inconsistency

Cause: ERR_PNPM_UNSUPPORTED_ENGINE (engines.pnpm mismatch), a lockfile-vs-package-manager mismatch, or a Node version difference.

Fix: align engines/packageManager in package.json, or enable Corepack. Node is 24 LTS by default (18 is deprecated). Put @vercel/speed-insights/@vercel/analytics in the package.json dependencies, not global (a frequent monorepo issue).


Routing and 404

A dynamic route returns 404

Cause: generateStaticParams doesn't return the target, the dynamic/dynamicParams setting, or a path that doesn't exist at build time.

Fix:

// 事前生成しないパスもオンデマンドで通す
export const dynamicParams = true; // 既定 true(false だと未生成は404)

export async function generateStaticParams() {
  // 少なくとも代表パスを返す。残りはオンデマンド生成(ISR)
  return (await getPopularSlugs()).map((slug) => ({ slug }));
}

For ISR behavior, the caching/ISR guide.

Doesn't display on a custom domain / DNS

Cause: DNS records (A/CNAME) unset, awaiting propagation, or the domain isn't added.

Fix: confirm the necessary records with vercel domains inspect <domain>. Keeping the TTL short speeds up switching/confirmation.


Environment variables "don't take effect"

This isn't an error but a sticking point, and there are very many consultations about it.

  • Environment-variable changes apply only to a new deployment. The existing production deployment doesn't change → redeploy.
  • To read it in the browser (client), the NEXT_PUBLIC_ prefix is needed. Conversely, don't attach it to secrets.
  • Set the value per environment (production/preview/development). If unset on preview, only preview falls over.
  • An invalid Edge Config connection string (Invalid Edge Config connection string) means the EDGE_CONFIG env is stale/deleted → update it.

Details in the environment-variables/secrets guide.


Cold start / slow

Cause: heavy function initialization (large dependencies, heavy work at startup), or the function executes every time on a cache miss.

Fix:

  • With Fluid Compute (default), concurrency and pre-warming work, and Node 20+'s bytecode cache works.
  • Do heavy startup work (large JSON parse, connection establishment) once outside the handler / lazily.
  • Don't call the function in the first place — make it a HIT with the ISR/CDN cache (caching). Confirm with x-vercel-cache.
  • Trim the bundle (remove unnecessary dependencies, 250MB limit).

Trouble-isolation checklist

  • Took primary-source information from Observability / Runtime Logs / Build Logs (don't guess)
  • 504 → make maxDuration explicit + separate long-running processing, timeout external APIs
  • 413 → uploads are client upload directly to Blob
  • ISR over 20MB → lighten the page output
  • Build failure → reproduce the same build locally, check output location/route/function pattern
  • 404 → generateStaticParams/dynamicParams, DNS
  • env not taking effect → redeploy, NEXT_PUBLIC_, per-environment settings
  • Slow → HIT with caching, Fluid, bundle reduction

Conclusion

Vercel troubleshooting can be crushed mechanically with "pinpoint the symptom with logs → category → cause → standard fix."

  1. Logs, not guessing (Observability / Runtime / Build Logs)
  2. 504 is separation, 413 is direct-to-Blob, ISR 20MB is lightening
  3. Build failures are local reproduction to isolate
  4. env is redeploy, NEXT_PUBLIC_, per-environment settings
  5. Cure slowness with cache HIT

I accompany you as a project through production incident investigation, permanent measures, and building out recurrence prevention. I also take spot investigations starting from the "an unexplained 504/500 is appearing" stage.

This article is based on the official documentation of the Vercel error list / Functions limitations (as of June 2026). Error codes and limits get updated, so confirm the latest in the official docs.

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Vercel apps, from design to production and cost optimization

Function design assuming Fluid Compute (safe global state, waitUntil, Cron), four-layer caching (ISR/CDN/Runtime Cache/Cache Components), safe deploys (preview/Promote/Instant Rollback/Rolling Releases), entry-point defense (Firewall/WAF/BotID), storage selection (Blob/Edge Config/Marketplace), and Active-CPU-billing-aware cost optimization. With experience running Next.js products on Vercel in production, I deliver fast, cheap, and secure.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading