LEARN · DEBUGGING GUIDE

Debugging 500 Errors on Nuxt Server API Routes

A 500 on your Nuxt API route? Get straight to the hidden causes, real-world symptoms, and practical fixes that actually work for Nuxt server errors.

IntermediateVue4 min read

What this usually means

A 500 error on a Nuxt server API route means the code inside your endpoint handler threw an unhandled exception or returned a rejected Promise. This isn't usually a frontend or routing issue—it's almost always a runtime problem in your serverMiddleware, handler logic, or imported modules. Causes range from missing environment variables (which Nuxt doesn't warn about), to schema validation failures, to subtle context issues in async code. In production, stack traces often get swallowed, making diagnosis harder.

( 01 )Fast diagnosis

The first ten minutes — establish facts before touching code.

  • 1Check server logs with `tail -n 50 .nuxt/nuxt-server.log` or wherever your server logs output.
  • 2Add a top-level try/catch in the failing API route to capture and log the actual exception.
  • 3Temporarily log `process.env` keys used in that route—missing secret/config is a classic cause.
  • 4Run the route locally with `NODE_ENV=development nuxt dev` and hit the endpoint directly.
  • 5Comment out all logic in the handler; if 500 disappears, restore chunks to isolate faulty code.
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchserver/api/*.ts or *.js (Nuxt 3 route handler files)
  • search.env and .env.production (for missing variables)
  • search.nuxt/nuxt-server.log or stdout logs on your server provider
  • searchImport paths—look for typos or failed imports in the handler file
  • searchpackage.json for mismatched dependencies (especially if dynamic import fails)
  • searchAny runtime schema or validation middleware (e.g., Zod, Joi, Yup)
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningAccessing process.env variables that are undefined or not exposed (use runtimeConfig instead in Nuxt 3)
  • warningImproperly handling async/await—missing await or not catching Promise rejections
  • warningInvalid JSON body/parsing errors (e.g., expecting req.body but getting undefined)
  • warningMismatched or missing imports, especially after refactoring file structure
  • warningThird-party packages that aren’t supported in serverless or edge runtimes
  • warningType errors—e.g., destructuring undefined in handler params
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildSwitch to Nuxt runtimeConfig for secrets/config instead of process.env (see nuxt.config.ts)
  • buildWrap handler logic in try/catch and log error.message and error.stack to server logs
  • buildAdd input validation early in the handler; throw 400 on bad data instead of letting runtime explode
  • buildCheck all imports in the handler—use absolute paths or aliases defined in jsconfig/tsconfig
  • buildReplace unsupported Node APIs (like fs) with cross-platform alternatives if deploying serverless
  • buildIf using typescript, run `nuxi typecheck` to catch handler signature errors early
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedTrigger the API route and confirm HTTP 200 or 4xx (not 500) returned
  • verifiedWatch server logs—ensure no error stack or 'unhandled error' printed when endpoint is hit
  • verifiedDeploy to staging and hit endpoint; verify logs stay clean in remote environment
  • verifiedAdd a healthy test route—call both and confirm only broken logic was fixed
  • verifiedWrite a quick integration test (e.g., with supertest) to POST and GET the endpoint
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningIgnoring missing environment variables—Nuxt doesn't error if runtimeConfig isn't wired up
  • warningRelying solely on client/browser errors—500s rarely bubble up to the frontend clearly
  • warningAssuming dev/prod parity—many 500s only show up on serverless or with minified prod builds
  • warningCatching errors in the handler but failing to respond (returning nothing also triggers 500)
  • warningLeaving process.env secret usage in source; always use runtimeConfig for server API routes
( 07 )War story

Silent 500s in a Nuxt 3 API Route on Vercel

Full-Stack EngineerNuxt 3.2.2, Node 18, Vercel serverless runtime, Typescript, Axios

Timeline

  1. 10:43Deployed new /api/subscribe route—worked locally, 500 on prod.
  2. 10:47Checked browser network tab: POST /api/subscribe returns 500, no body.
  3. 10:51Vercel logs: 'Unhandled error: TypeError: Cannot read property 'EMAIL_API_KEY' of undefined'
  4. 11:01Compared .env, found missing EMAIL_API_KEY in Vercel project settings.
  5. 11:05Added EMAIL_API_KEY to Vercel, re-deployed—still fails.
  6. 11:10Realized handler was using process.env directly, not useRuntimeConfig().
  7. 11:14Refactored to use runtimeConfig.public, redeployed: endpoint returns 200.

We shipped a new Nuxt 3 API route to handle newsletter subscriptions. Everything worked locally, but production started throwing 500s with no error in the frontend.

The Vercel logs finally gave it away: my handler was accessing process.env.EMAIL_API_KEY, but Nuxt 3 expects you to pull secrets from runtimeConfig. So the key was always undefined on Vercel, even though it was in project env settings.

It took a refactor of every process.env reference to use useRuntimeConfig() before the endpoint returned a proper 200. Staging and prod now match, and our error reporting is much clearer.

Root cause

Handler used process.env instead of runtimeConfig for secrets; Vercel didn't inject process.env at runtime.

The fix

Switched all secret/config access in handlers to use useRuntimeConfig().

The lesson

Don't use process.env directly in Nuxt 3 server handlers—always go through runtimeConfig to avoid invisible 500s.

( 08 )Nuxt 3 API Route Handler Context and gotchas

Nuxt 3 server API routes (in /server/api/*.ts) run in their own context. process.env is NOT available at runtime in most host environments, especially serverless. Instead, Nuxt expects all runtime secrets and configuration to come from runtimeConfig, injected at build and runtime.

If you access process.env in your handler, it might work locally, but fail silently in production. Always use useRuntimeConfig() to pull values—e.g., `const config = useRuntimeConfig();`.

( 09 )Error Handling Patterns for Nuxt API Handlers

Uncaught errors in a Nuxt API handler bubble up and trigger a 500 with no helpful message in the response. Always wrap your logic in a try/catch, and include logging:

Example: `try { ... } catch (error) { console.error(error); return sendError(event, createError({ statusCode: 500, statusMessage: error.message })); }`

( 10 )Common Production/Dev Mismatches

Locally, your .env file is loaded and process.env works. On Vercel/Netlify, you need to declare environment variables in the project UI, and only runtimeConfig vars are injected into the server handler context.

If your route works in dev but fails in prod, immediately audit every process.env usage in server-side files.

( 11 )Pinpointing Faulty Imports and Schema Validators

A failed import (bad path or missing package) in your handler file throws immediately at route load, causing unexplained 500s. Node won’t always show a stack trace unless you log it explicitly.

If you use schema validators (like Zod/Joi), a malformed or missing schema can throw synchronously on import—add guard clauses and log schema construction if you suspect this.

Frequently asked questions

Why do my Nuxt 3 API routes work in development but throw 500 in production?

process.env is available in local dev but not at runtime in most serverless prod hosts. Always use runtimeConfig to access secrets and config in Nuxt 3 server handlers.

How can I see the real error behind a 500 from a Nuxt server API route?

Wrap your handler in try/catch and log error.message and error.stack. Check .nuxt/nuxt-server.log or your cloud provider's function logs for the real exception.

Does Nuxt expose stack traces to the frontend for API route errors?

No. By default, 500 errors only return 'Internal server error' to the client. The stack trace is only in server logs unless you explicitly add it to the response (not recommended in prod).

What's the safest way to handle config/secrets in Nuxt 3 server API routes?

Declare them in runtimeConfig in nuxt.config.ts, set them in your deployment's env vars, and always access via useRuntimeConfig() in handlers.