Skip to content

App Router API Routes 404 Error

Problem Statement

When working with Next.js 13+ using the App Router (app directory), you may encounter a 404 Not Found error when trying to access API routes through tools like Postman or directly via browser. This typically happens even when:

  1. You've created API route files following the traditional Pages Router convention
  2. Your file structure appears to be correct
  3. The routes work during local development but fail in production builds

The common symptoms include:

  • Receiving 404 errors for GET, POST, or other HTTP requests
  • Routes working in development mode (npm run dev) but not in production
  • API endpoints returning 404 regardless of directory structure adjustments

Solution 1: Correct File Naming and Route Handler Syntax

The most common cause is incorrect file naming conventions and handler implementation in the App Router.

Required Fixes:

  1. Correct File Location and Naming

    • Place API routes in /app/api/[route-name]/ directories
    • Rename handlers to route.js or route.ts (not all.js, index.js, etc)
    bash
    └── app/
        └── api/
            └── admin/  # URL: /api/admin
                └── route.js  # Mandatory filename
  2. Export Named HTTP Methods

    • Use named exports (GET, POST, etc) instead of default exports
    • Import NextResponse and NextRequest from next/server
    js
    import { NextResponse } from 'next/server';
    import { PrismaClient } from '@prisma/client';
    
    const prisma = new PrismaClient();
    
    export async function GET(request) {
      try {
        const admins = await prisma.admin.findMany();
        return NextResponse.json(admins, { status: 200 });
      } catch (error) {
        return NextResponse.json(
          { error: 'Failed to get admins' },
          { status: 500 }
        );
      }
    }

Key Differences from Pages Router

  • No need to check req.method - Handlers only respond to their named HTTP verb
  • Response objects use NextResponse.json() instead of res.status().json()
  • API path is determined by directory structure, not file name

Solution 2: Fix Static Export Conflicts (For Production Builds)

If your routes work locally but fail in production, check your next.config.js:

js
/** @type {import('next').NextConfig} */
module.exports = {
  // Remove this line to enable server features
  // output: 'export', // ⛔️ Causes API routes to fail

  // Correct configuration for API routes:
  eslint: {
    ignoreDuringBuilds: true,
  },
  images: { unoptimized: true }
};

Why This Happens in Production

  • output: 'export' configures Next.js for static HTML export
  • API routes require server-side execution and disappear in static exports
  • Solution: Remove output: 'export' if using server features

Additional Tips

Handling Different HTTP Methods

js
export async function POST(request) {
  const body = await request.json();  // Parse JSON body
  // Process data...
  return NextResponse.json({ success: true });
}

export async function PUT(request) {
  // PUT handler logic
}

Accessing Request Data

  • Use await request.json() for JSON payloads
  • Access query parameters with request.nextUrl.searchParams:
    js
    export async function GET(request) {
      const searchParams = request.nextUrl.searchParams;
      const id = searchParams.get('id');
      // Fetch data using id
    }

Testing Your API Routes

bash
# Test GET request
curl http://localhost:3000/api/admin

# Test POST request with JSON body
curl -X POST http://localhost:3000/api/admin \
  -H "Content-Type: application/json" \
  -d '{"name": "New Admin"}'

Production Deployment

  • Ensure your hosting platform supports Node.js servers
  • For serverless environments (Vercel, AWS Lambda):
    js
    module.exports = {
      output: 'standalone', // Auto-copies needed files for deployment
    };

By following these conventions and solutions, you should eliminate 404 errors from your App Router API routes. Remember to consistently use route.js naming and export HTTP methods by name to align with Next.js 13+ App Router requirements.