next.js: API routes returning a 405 on Vercel, fine in dev/local

Link to the code that reproduces this issue

https://codesandbox.io/p/sandbox/agitated-dubinsky-8s9pvw?file=/package.json:1,1

To Reproduce

  1. Have a NextJS app using the pages directory
  2. Include an API route in pages/api that returns a JSON response
  3. Hit that endpoint in your component, see it works locally
  4. Deploy to Vercel, see that you get a 405

Current vs. Expected behavior

In current 13.4.x versions, there is no issue with these API routes, things are working fine. Upgrading to 13.5.1, all pages/api routes that return a 200 JSON response are getting a 405 Method Not Allowed only once deployed to Vercel.

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: linux
      Arch: x64
      Version: #1 SMP Fri Jan 27 02:56:13 UTC 2023
    Binaries:
      Node: 18.18.0
      npm: 9.8.1
      Yarn: 1.22.19
      pnpm: 8.7.6
    Relevant Packages:
      next: 13.5.2-canary.1
      eslint-config-next: 13.5.2-canary.1
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.2.2
    Next.js Config:
      output: N/A

Which area(s) are affected? (Select all that apply)

Middleware / Edge (API routes, runtime)

Additional context

I am currently working on the above reproduction, but wanted to get this out as I think it relates to work done in https://github.com/vercel/next.js/pull/51534

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 22 (1 by maintainers)

Commits related to this issue

Most upvoted comments

I finally figured out the issue. @Alex1899 was closest, although I never got an error for it in logs like he did, I discovered it haphazardly through the CLI with Next 14 when loading up local dev. We have an env var that we only include on production, that was not added for Preview deploys in Vercel. I added it and builds magically started working.

I think there should be better logs around missing env var’s per environment, or better error handling around when a build is missing vars. Not sure best course of action but that was a doozy to figure out without better messaging or details.

I believe the problem is due to static rendering.

Next thinks your page doesn’t have any need for data fetching/uploading if you don’t use a dynamic function, so it renders the same page for everyone and your outgoing request can’t be run because it’s static HTML that’s delivered from a CDN/edge server.

Here’s how I fixed it:

import {headers} from 'next/headers'

export default function NewPage() {
    // hack page into dynamic rendering
    const headersList = headers()

    return (
        ...
    )
}

@leerob I think this is a bug has been reported on several other issues. Examples:

  • Use a third-party data fetching tool like Prisma in Server Components, without the use of a Dynamic Function
  • Call a Server Action without the use of a Dynamic Function

@shuding @leerob sorry to ping directly but want to get some visibility on this, can’t upgrade at the moment and am stumped on to what could be the issue. Hard to replicate in Code Sandbox since it’s not deployed to Vercel.

@wadehammes To add more context to my solution, during build time the file location are change hence the application lost the path of the file email template which is different during development. Hence the file was not found.

check logs on /<app_name>/logs

`

import path from ‘path’;

// Change the below

const emailResponseHTML = await ejs.renderFile(

  './email/contactMailer.ejs',

  { fullName: fullName }

);

// To ths below after the above import

const emailResponseHTML = await ejs.renderFile(

  `${path.resolve(process.cwd(), 'email')}/contactMailer.ejs`,

  { fullName: fullName }

);

`

I don’t think this relates to my issue

Oops, sorry for the inadvertent mention. In my case, I’m quite ashamed to say, I forgot to commit the route.ts to the repo 😱 All working fine on latest NextJS. So seems like a different issue to this one. I’ve removed the above commit from my repo but seems there’s no way to delete the mention on GitHub. Sorry for the noise.