Fetching Next.js API Route in the app directory gives 404 Not Found

I am struggling with Next.js 13's app routing. It always gives me a 404 Not Found when I try to access, for example from Postmann.

I have this file structure:

enter image description here

And for example, one of my API files is:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

export default async function all(req, res) {
    if (req.method !== 'GET') {
        return res.status(405).json({ error: 'Method not allowed' });
    }

    try {
        // Get all admins using Prisma
        const admins = await prisma.admin.findMany();

        return res.status(200).json(admins);
    }
    catch (error) {
        return res.status(500).json({ error: 'Failed to get admins' });
    }
}

When I send a GET localhost:3000/api/admin/all it always responds with a 404. Couldn't find where is the error.

I tried other file or folder namings. Calling from my own app, using the curl command, or using Postman. My other API routes give the same 404.

Upvotes: 26

Views: 47382

Answers (3)

Kanishka Sahu
Kanishka Sahu

Reputation: 317

Solved: Next.js Issue with app Directory in Production Build giving 404 not found but working in localhost and local bhuils

After spending almost 6 hours on the issue, I finally solved it!

If you're using Next.js >=14.0.0 with the app directory structure (e.g., app/api/test/route.ts or app/api/test/route.js), and everything works fine in localhost but not in the production build on platforms like Vercel or Amplify, here's the fix:

Problem:

Ensure that your next.config.js file does not include "output": "export".

Correct next.config.js Example:

/** @type {import('next').NextConfig} */
const nextConfig = {
  eslint: {
    ignoreDuringBuilds: true,
  },
  images: { unoptimized: true },
};

module.exports = nextConfig;

Steps:

  1. Update your next.config.js as shown above.
  2. Build your project again.
  3. Deploy to your production platform.
  4. Enjoy a hassle-free build!

Happy coding! 😊

Upvotes: 0

Youssouf Oumar
Youssouf Oumar

Reputation: 46151

An API Route should be in a file called route.js. Meaning app/api/admin/all.js should be app/api/admin/route.js, with the corresponding URL being /api/admin. Also, the functions inside should use a specific definition:

export async function GET(request) {}

GET can be replaced with POST, PUT, PATCH, etc. In your case, it would be:

// Notice from where NextResponse is imported:
import { NextResponse } from "next/server";

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

// Notice the function definition:
export async function GET(req) {
  return NextResponse.json(
    { error: "Method not allowed" },
    {
      status: 405
    }
  );
}

// Notice the function definition:
export async function POST(req) {
  try {
    // Get all admins using Prisma
    const admins = await prisma.admin.findMany();

    return NextResponse.json(admins, {
      status: 200,
    });
  } catch (error) {
    return NextResponse.json(
      { error: "Failed to get admins" },
      {
        status: 500,
      }
    );
  }
}

Upvotes: 37

Mary Etokwudo
Mary Etokwudo

Reputation: 31

In addition to Youssouf's answer (which I found very helpful), if you have problems getting the content of request.body, use const body = await request.json() to get the body.

https://developer.mozilla.org/en-US/docs/Web/API/Request/json

Upvotes: 3

Related Questions