Dynamic API routes return 404 on Vercel but not locally (Next 14.0.1, app router)
Answered
Ben Greene posted this in #help-forum
Ben GreeneOP
Hi all - I have a very annoying error that I can't seem to fix. This is on Next 14.0.1 using app router.
The specific behavior is that certain API routes are returning 404 errors instead of loading, but only when deployed to Vercel. The attached image shows the directory structure of the API routes - the specific routes that fail are
There does not appear to be any significant difference in the
Thank you ðŸ™
The specific behavior is that certain API routes are returning 404 errors instead of loading, but only when deployed to Vercel. The attached image shows the directory structure of the API routes - the specific routes that fail are
api/programs/[id]
and api/programs/page/[page]
. The api/users
, api/users/[id]
, and api/programs
routes all return results.There does not appear to be any significant difference in the
route.ts
files. Does anyone have suggestions on what I could try?Thank you ðŸ™
Answered by Ben Greene
Update: although the why still eludes us, we were able to resolve the problem. The cause seems to be having a directory in the root of the project (at the same level as
app
) called api
. This was being used for some library files. Renaming that directory from api
to apiServices
seems to be the only change required to make the dynamic routes begin functioning properly again.116 Replies
Siricid woodwasp
where are you calling those apis in client or server?
Ben GreeneOP
@Siricid woodwasp Sorry, I'm not completely sure I understand your question. Whether I make the API call from within a component or directly via the web browser, I get the 404 either way.
Siricid woodwasp
i mean how are you calling api end points in your app like fetch("api/user")
Ben GreeneOP
Ahh -
const response = await get(
programs/page/${page});
Siricid woodwasp
are those client components?
Ben GreeneOP
It's a lib used within client components, I believe - will need to check, currenly away from desk
Ben GreeneOP
confimed, client components
but I'm fairly sure that the problem is somehow elsewhere, because accessing the API call directly from the browser also fails 😕
Ben GreeneOP
@Siricid woodwasp I think I've made some progress - this seems to only hit API calls that have a dynamic element in them, e.g.
programs/page/[page]
- it turns out that users/[id]
doesn't work either (on Vercel - still works fine locally).Northern snakehead
just going to jump in here and follow this as I believe i have the same issue 🙂
Ben GreeneOP
I updated the title to be a bit more specific and hopefully garner more assistance ðŸ™
Z4NR34L
Yo Folks. Let's solve this - at the beginning @Ben Greene, could you provide us with this endpoint code/repository url (if it's public) or minimal reproduction?
https://nextjs-faq.com/minimal-reproduction-repository
https://nextjs-faq.com/minimal-reproduction-repository
also if that's possible please share an screenshot of that 404 error which you get - this will help assign if we have problem with vercel (platform) or nextjs (your code)
Ben GreeneOP
@Z4NR34L appreciate your help!
Here's a screenshot of the 404 on Vercel (left) and the 200 on localhost (right):
Here's a screenshot of the 404 on Vercel (left) and the 200 on localhost (right):
The repo is not public, so it'll take me some time to create a new test repo
While I get that ready - my colleague believes that not having
NEXT_PUBLIC_API_URL
defined in the ENV variables may be a cause of this problem - could that be the case? And if so, how is one supposed to generate that in Vercel preview deployments?Z4NR34L
Ok, There is no chance to get into the cause of this issue without even minimal reproduction or code, we can just guess, and env variables is the first thing that should be double checked before deployment 😄
scan your code which env vars are you using, remember that if you use variable in route handler you dont need to add
NEXT_PUBLIC_
prefix as it’s executed server-sideBen GreeneOP
lol yeah, I'm working on a repro now
Z4NR34L
if you don't have any hardcoded credentials, just post endpoint code here, that should be fine for now
Ben GreeneOP
Sure, so here is the contents of
app/api/programs/page/[page]/route.ts
:import { PrismaClient } from '@prisma/client';
import { NextRequest, NextResponse } from "next/server";
const prisma = new PrismaClient();
export async function GET(request: NextRequest) {
const prisma = new PrismaClient();
const programs = await prisma.program.findMany();
return NextResponse.json(programs);
}
Z4NR34L
also check your env vars on vercel, if you have selected all needed environments (Development/Preview/Production)
Ben GreeneOP
And that exact same code works in
app/api/programs/route.ts
Z4NR34L
huh, I see
are you running
prisma generate
during the build step? 😄Ben GreeneOP
Z4NR34L
ok, did you checked env vars?
you need preview + production on vercerl to get it work there
Ben GreeneOP
Well I don't have
DATABASE_URL
at all, but the above returns data from the DB on the non-dynamic routeI have
POSTGRES_URL
Z4NR34L
ok, I meant any env vars that are used there
first, let's try to check if everything is just building fine, replace this code with:
and verify if you get back number you provided in path
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest, {params}: { params: { page: number }}) {
return NextResponse.json({page: params.page});
}
and verify if you get back number you provided in path
Ben GreeneOP
pushed to vercel
still a 404
I'm not an expert on Next.js by any means, but I don't think the code content of the route itself is playing much of a role
Z4NR34L
that's what we needed to verify
Now, please share your next.config and middleware (if any), also vercel.json if used
and to be sure, post file path in repository, and URL without domain
Ben GreeneOP
next.config.js
:/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
images: {
domains: ["lh3.googleusercontent.com", "vercel.com"],
},
async redirects() {
return [
{
source: "/github",
destination: "https://github.com/steven-tey/precedent",
permanent: false,
},
];
},
};
module.exports = nextConfig;
(I should probably change that github source from the repo I cloned)
middleware.ts
:import createMiddleware from 'next-intl/middleware';
import { LOCALES } from '@/lib/constants';
export default createMiddleware({
// A list of all locales that are supported
locales: LOCALES,
// If this locale is matched, pathnames work without a prefix (e.g. `/about`)
defaultLocale: 'en'
});
export const config = {
// Skip all paths that should not be internationalized. This example skips the
// folders "api", "_next" and all files with an extension (e.g. favicon.ico)
matcher: ['/((?!api|_next|.*\\..*).*)']
};
No
vercel.json
Z4NR34L
ok, so url without domain and file path in repository - just for double-check
also please check your vercel logs if there is no errors 😉
Ben GreeneOP
the relative file path (copied from VS Code) is:
app/api/programs/page/[page]/route.ts
And the URL without domain:
/api/programs/page/1
the deployment logs say 0 errors and 0 warnings
I've read through it and not seen anything particularly interesting
although it does identify the routes in question:
Route (app) Size First Load JS
┌ ○ /_not-found 882 B 89.2 kB
├ λ /[locale] 559 B 124 kB
├ λ /[locale]/about 550 B 124 kB
├ λ /[locale]/auth/error 957 B 124 kB
├ λ /[locale]/auth/signin 863 B 135 kB
├ λ /[locale]/auth/verify-request 1 kB 124 kB
├ λ /[locale]/programs 2.24 kB 125 kB
├ λ /[locale]/programs/[id] 2.4 kB 125 kB
├ λ /[locale]/programs/edit/[id] 1.11 kB 227 kB
├ λ /[locale]/programs/new 572 B 227 kB
├ λ /[locale]/users/[id]/edit 1.59 kB 125 kB
├ λ /api/auth/[...nextauth] 0 B 0 B
├ λ /api/programs 0 B 0 B
├ λ /api/programs/details/[id] 0 B 0 B
├ λ /api/programs/page/[page] 0 B 0 B
├ ○ /api/users 0 B 0 B
└ λ /api/users/[id] 0 B 0 B
+ First Load JS shared by all 88.3 kB
├ chunks/472-e4fe7de096be0269.js 33 kB
├ chunks/fd9d1056-1de2bf583fdbc1a8.js 53.2 kB
├ chunks/main-app-892c3dff08e9cd4c.js 232 B
â”” chunks/webpack-fbec2224bf4eac50.js 1.87 kB
Z4NR34L
huh
Ben GreeneOP
sounds like we're on the same page
Z4NR34L
wait a sec
I'm using dynamic route handlers in my projects but I see that there is small difference
I'm on edge runtime
try to change our test route to edge 😄
export const runtime = 'edge'
Ben GreeneOP
It's off ðŸ¿
👎 😞
Z4NR34L
you are using next-auth
you are not locking those urls? 😄
Ben GreeneOP
...?
Z4NR34L
maybe I will ask in other words: are you using next-auth to auth users before accessing those routes?
I mean api routes
Ben GreeneOP
oh - no, I'm not - though I certainly will down the line
Z4NR34L
the problem is - I cannot reproduce that issue in clean next.js - so maybe one of packages that you had used is messing around
but let's try one more thing - remove middleware for now
just to get as clean access to route as possible
Ben GreeneOP
What version of nextjs are you on
Ray
do you see any errors from the logs on vercel dashboard?
Ben GreeneOP
not really:
though I didn't expect a 204...
Z4NR34L
I'm using 14.0.2 currently
you are viewing a HEAD method request log, and you are supposed to make an GET method
Ben GreeneOP
yeah.... weird
Z4NR34L
but /api/programs is working fine from what I can see
Ben GreeneOP
correct
Z4NR34L
but, can you see more logs on vercel now?
Ben GreeneOP
this is so bizarre
here's chrome inspector:
but there's no corresponding 404 in vercel:
I'm on 14.0.1, so I'm gonna upgrade that just to see
Z4NR34L
there is still middleware that's working
try disabling/removing it for now
Ben GreeneOP
sorry that middleware is from a different branch
Z4NR34L
ok
I remember that I was not using next-intl for a reason with appdir 😄 But not sure what exacly problem that was
Ben GreeneOP
::blinks::
Z4NR34L
I've made my own middlware for locales routing
/api/users/[id]
is not working too from what I checked nowBen GreeneOP
correct
no dynamic api route is
I wonder if it worked when I started this with 13.5......
Z4NR34L
hmm, that's pretty wide problem, and I think I'm not able to help you without testing this right on your repository :/
Ray
i can't reproduce it too
14.0.1 also work for me
https://test-page-kappa.vercel.app/api/programs/page/2
https://test-page-kappa.vercel.app/api/programs/page/2
Ben GreeneOP
Interesting.
Also interesting: after upgrading to 14.0.2, I now get this error:
Also interesting: after upgrading to 14.0.2, I now get this error:
app/api/auth/[...nextauth]/route.ts
Type error: Route "app/api/auth/[...nextauth]/route.ts" does not match the required types of a Next.js Route.
"authOptions" is not a valid Route export field.
Ben GreeneOP
^^^ this is not so much interesting as just annoying
Ray
what version of next-auth are you using
Ben GreeneOP
4.22.1
Ray
does the api work if you change the middleware file to _middleware
Ben GreeneOP
sorry had to get back to a working state - so just rename it to _middleware...
Ben GreeneOP
I mean the short answer is that obviously kills my locale-enabled pages... working on actually getting a successful deploy through Vercel... been making a lot of changes quickly...
Ok! Results are in, and removing/renaming middleware file does not make the dynamic API routes functional.
Z4NR34L
So that case too wide to debug it just by telling you what to do, badly. Easiest way would be making a reproduction or allowing us to view the origin code
Ben GreeneOP
@Z4NR34L I DMed you
Z4NR34L
Update: This topic is in progress - if we find a solution, I'll post it there
Ben GreeneOP
Update: although the why still eludes us, we were able to resolve the problem. The cause seems to be having a directory in the root of the project (at the same level as
app
) called api
. This was being used for some library files. Renaming that directory from api
to apiServices
seems to be the only change required to make the dynamic routes begin functioning properly again.Answer
Z4NR34L
brilliant 😄
Ben GreeneOP
Right?! 😞
Z4NR34L
that's perfect example why it's important for others to see whole code/repository or reproduction 😄
Berger Picard
hey sorry to revive this, I'm having the exact same issue but with localhost
/api/players returns 404
even in postman
its really bare too
risky
why are you not using
route.ts
as players.ts
is going to be ignored.... also for future can you make a new thread as everyones are diferentBerger Picard
why
risky
what do you mean by "why"?
your
/api
isn't going to be usable, idk if thats intentional