LEARN · DEBUGGING GUIDE

Diagnosing 404s from Next.js API Routes That Should Exist

Your Next.js API endpoint is returning a 404, and it shouldn't. Get to the root cause with step-by-step debugging tailored for real-world Next.js pitfalls.

BeginnerNext.js4 min read

What this usually means

A 404 from a Next.js API route typically means that Next does not recognize the route as an API endpoint. This can result from misnaming the file, incorrect directory structure, build artifacts, case sensitivity differences (especially between local dev and deployment), or misconfigured rewrites and custom servers. Sometimes, an accidental catch-all dynamic route or a middleware interaction will swallow the intended API call. The same route can behave differently between dev and production due to case sensitivity or missing build output.

( 01 )Fast diagnosis

The first ten minutes — establish facts before touching code.

  • 1Check the exact file path: ensure /pages/api/foo.js (not Foo.js or foo/index.js unless intended).
  • 2Run 'ls -l pages/api' to verify the file exists and has correct casing.
  • 3Visit http://localhost:3000/api/foo in dev and after 'next build && next start'.
  • 4On Vercel, check the 'Functions' tab: is your route deployed as an API endpoint?
  • 5Look for interfering rewrites/redirects in next.config.js or vercel.json.
  • 6Scan for dynamic catch-all routes (e.g., [...slug].js) that could override intended route.
( 02 )Where to look

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

  • searchpages/api/<route>.js or .ts
  • searchnext.config.js for rewrites/redirects
  • search.next/routes-manifest.json after build
  • searchVercel dashboard > Functions tab
  • searchServerless logs (e.g., Vercel, AWS Lambda, Docker logs)
  • searchDeployment build logs (look for 'Compiled Successfully' message and missing endpoints)
( 03 )Common root causes

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

  • warningFile named Foo.js on Mac (works locally) but production expects foo.js (Linux case sensitive)
  • warningForgot .js/.ts extension (wrote foo instead of foo.js)
  • warningRoute inside /pages/api/foo/index.js, but requesting /api/foo (Next expects /api/foo not /api/foo/index)
  • warningDynamic route ([id].js) intercepting static route
  • warningAPI file not included in build output (ignored by .gitignore, missing in deployment)
  • warningnext.config.js rewrite sends /api/* elsewhere
( 04 )Fix patterns

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

  • buildRename files to use consistent lowercase, e.g., foo.js not Foo.js
  • buildMove misplaced files into /pages/api/
  • buildAdd missing file extensions
  • buildAdjust next.config.js to remove conflicting rewrites or redirects
  • buildEnsure all API files are committed and deployed (git status, .gitignore)
  • buildFor dynamic API routes, verify param patterns and request URLs match
( 05 )How to verify

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

  • verifiedcurl -i http://localhost:3000/api/foo after fixing; confirm HTTP 200 or 500, not 404
  • verifiedRedeploy and test the endpoint in your production environment
  • verifiedCheck build output in .next/routes-manifest.json for the route
  • verifiedSee the endpoint listed in Vercel's Functions tab
  • verifiedRemove all custom rewrites and confirm the route works without them
  • verifiedTest with both GET and POST if you support both methods
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningIgnoring case sensitivity differences between Mac/Windows (case-insensitive) and Linux (case-sensitive)
  • warningPushing changes without checking the deployed artifact file tree
  • warningBlindly adding rewrites to 'fix' the path instead of correcting the actual file
  • warningAssuming the dev server matches the production server behavior exactly
  • warningLeaving .gitignore too broad and excluding API files
( 07 )War story

Missing API Route After Deploy Due to File Case

Full-Stack DeveloperNext.js 12, Vercel, MacOS local dev

Timeline

  1. 10:00QA reports /api/fetchUser returns 404 in staging.
  2. 10:03Developer verifies /api/fetchUser.js exists locally and works on localhost.
  3. 10:10Examines Vercel deployment logs; sees no /api/fetchUser function listed.
  4. 10:13Runs 'ls -l pages/api' on Mac, sees FetchUser.js (capital F).
  5. 10:15Renames FetchUser.js to fetchUser.js, commits, and redeploys.
  6. 10:19QA confirms /api/fetchUser now returns 200 in staging.

I got a Slack ping from QA: the /api/fetchUser route was returning 404 after a routine deployment. Locally, everything worked—my Mac served the route just fine.

First, I checked the file tree and saw I'd accidentally named the handler FetchUser.js with a capital F. On Mac, the filesystem's case insensitivity masked the problem, but in Vercel's build (which runs Linux), the API route wasn't recognized.

Renaming the file to fetchUser.js, pushing, and redeploying immediately fixed the 404. Since then, I always double-check file casing before merging or deploying Next.js API routes.

Root cause

API file used incorrect casing, which worked on local (Mac) but not on Vercel (Linux).

The fix

Renamed FetchUser.js to fetchUser.js and redeployed.

The lesson

Always confirm Next.js API route files use correct lowercase names, especially when moving between case-insensitive and case-sensitive environments.

( 08 )Why Next.js API Route Resolution Can Fail Subtly

Next.js relies on convention: files under /pages/api become API endpoints. If you violate naming or location conventions—especially with case or extensions—the route silently fails to register, resulting in a 404.

On Mac or Windows, you might not notice because those filesystems are case-insensitive by default. Linux-based servers (including Vercel and most CI images) are case-sensitive, so a missing lowercase match means no endpoint.

( 09 )Detecting Deployment-Only API Route Failures

It's common for a route to work locally but fail in production. To catch this, always build with 'next build && next start' locally before deploying, and validate route presence in the build output (inspect .next/routes-manifest.json).

On Vercel, use the dashboard's 'Functions' tab: your API endpoints should be listed there. If missing, something is wrong with the file, its location, or your build configuration.

( 10 )Rewrites, Redirects, and Middleware: Unexpected Interference

A misconfigured rewrite in next.config.js can unintentionally capture or redirect API requests elsewhere, leading to 404s even if the file exists. Check for patterns like '/api/*' in rewrites or redirects.

Similarly, custom _middleware (especially at the root or /api level) can intercept requests and send unexpected responses. Disable middleware to isolate the problem.

Frequently asked questions

Can I use uppercase letters in my API file names?

No. Always use lowercase file names for Next.js API routes. Uppercase letters may work locally on Mac/Windows but fail in production Linux environments.

Does Next.js support nested API routes?

Yes. You can nest API files under pages/api/, such as pages/api/user/login.js, which will map to /api/user/login. Be precise with directory and file names.

Why does my API route work with 'next dev' but not after build?

Development mode is more forgiving and runs from source. Production mode relies on the build output, which strictly follows case and structure. Always test with 'next build && next start'.

I'm using TypeScript—do I need to configure anything special?

No extra config is needed, but your API route files must still be under pages/api and use .ts or .js extensions. Avoid .ts files that don't export a default handler.