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:
- You've created API route files following the traditional Pages Router convention
- Your file structure appears to be correct
- 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:
Correct File Location and Naming
- Place API routes in
/app/api/[route-name]/
directories - Rename handlers to
route.js
orroute.ts
(notall.js
,index.js
, etc)
bash└── app/ └── api/ └── admin/ # URL: /api/admin └── route.js # Mandatory filename
- Place API routes in
Export Named HTTP Methods
- Use named exports (
GET
,POST
, etc) instead of default exports - Import
NextResponse
andNextRequest
fromnext/server
jsimport { 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 } ); } }
- Use named exports (
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 ofres.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
:
/** @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
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
:jsexport async function GET(request) { const searchParams = request.nextUrl.searchParams; const id = searchParams.get('id'); // Fetch data using id }
Testing Your API Routes
# 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.