nitro icon indicating copy to clipboard operation
nitro copied to clipboard

Vercel ISR: Direct navigation to an ISR route returns 404 (Nuxt 4.1.3 / Nitro 2.12.7)

Open ps-20x opened this issue 2 months ago • 4 comments

Environment

nuxt: "4.1.3", nitropack: "2.12.7", node: "Vercel runtime (Node 22.x)"

Nuxt config (relevant excerpt)

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    "/fachrichtungen": {
      isr: {
        allowQuery: ["location"],
        expiration: 3600,
        passQuery: true,
      },
    },
  },
})

Deployment target

  • Vercel (Free plan)
  • Zero-config deployment using Nitro’s vercel preset

Reproduction

Steps:

  1. Open the live URL above directly in a new tab (or hard-refresh).
  2. Observe a 404.
  3. From the home page (/), click a link to the ISR route (client-side navigation).
  4. First hit renders; subsequent hits are served from cache as expected.

Describe the bug

Incremental Static Regeneration works on client-side navigation, but direct navigation (entering the URL or hard-refresh) to an ISR route returns a 404 on Vercel.

This looks like the same problem discussed in Nuxt issue nuxt/nuxt#33316 which was closed after a Nitro fix, but it still reproduces with current versions.

Expected behavior

Direct navigation to an ISR route should generate (on first request) and then serve the cached page (or serve cached content if it already exists), same as client-side navigation.

Actual behavior

  • Direct navigation / hard-refresh returns 404 for the ISR route.
  • Client-side navigation to the same route works (first request generates, subsequent are cached).

Additional context

  • The behavior mirrors nuxt/nuxt#33316 (“Direct navigation to ISR redirects/404 on Vercel”) which was marked fixed upstream in Nitro, but the issue still occurs on Nuxt 4.1.3 / Nitro 2.12.7.
  • No custom vercel.json / edge config; this is a minimal setup to isolate Nitro/ISR behavior.
  • Linked to this PR: https://github.com/nitrojs/nitro/pull/3595

Logs

* Vercel request shows 404 for direct navigation to `/fachrichtungen`.

[request error] [fatal] [GET] /fachrichtungen-isr?
 H3Error: Page Not Found
    at createError$1 (file:///var/task/chunks/nitro/nitro.mjs:943:15)
    at createError (file:///var/task/chunks/build/server.mjs:478:21)
    at setup (file:///var/task/chunks/build/_...slug_-DkjO_2q9.mjs:5931:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  cause: { fatal: true, statusCode: 404, statusMessage: 'Page Not Found' },
  statusCode: 404,
  fatal: true,
  unhandled: false,
  statusMessage: 'Page Not Found',
  data: undefined
}

ps-20x avatar Oct 13 '25 16:10 ps-20x

Thanks for spending time to make a reproduction and a detailed issue @ps-20x

The issue you are facing is likely due to the usage of allowQuery + passQuery, which is a known issue and i have a draft solution for it (https://github.com/nitrojs/nitro/pull/3539) (pending for some infra changes i will check it again)

pi0 avatar Oct 13 '25 18:10 pi0

@ps-20x can you try this:

 "resolutions": {
    "nitropack": "https://pkg.pr.new/nitrojs/nitro/nitropack@3539#2"
  },

pi0 avatar Oct 14 '25 10:10 pi0

@pi0 thank you for your quick response. I quickly adapted it in the minimal reproduction and it looks like it's working. Anything else that I should take a closer look at?

ps-20x avatar Oct 14 '25 13:10 ps-20x

It is more than enough thanks for confirming!

pi0 avatar Oct 14 '25 13:10 pi0