Inconsistent catch-all route behavior between local build & Vercel

I’m seeing inconsistent routing behavior between visiting my local Next.js production build and my Vercel production deployment.

Setup

  • Next.js v15.2.3
  • Using pages router
  • Node v20.17.0

This is a simplified representation of the routes

pages/
├── [[...catchallslug]].tsx      <-- Top-level catch-all route. Requests external CMS
└── shop/
    └── shirts/
        └── [...slug].tsx       <-- Nested dynamic route for shirt product pages. These should be generated on buildtime

Route Configuration:

  • [...slug].tsx uses fallback: false with a hardcoded array of paths:
    • /shop/shirts/adidas/original-tee
    • /shop/shirts/adidas/performance-tee
  • [[...catchallslug]].tsx uses fallback: 'blocking' to handle unmatched routes

The Issue:

Local behavior (expected): When visiting /shop/shirts/adidas/something (a non-generated path), the request falls back to the top-level catch-all route [[...catchallslug]].tsx.

Vercel behavior (unexpected): The same URL triggers [...slug].tsx and runs its getStaticProps , despite fallback: false . I expect this to return a 404 since the path wasn’t pre-generated. Also, the response includes the header x-matched-path: /[[...catchallslug]] , indicating Vercel internally knows it should match the optional catch-all route, yet it still renders the [...slug].tsx template and executes its getStaticProps

Key observation: When I remove [[...catchallslug]].tsx entirely, Vercel correctly returns a 404 for /shop/shirts/adidas/something .

Why does the presence of a top-level optional catch-all route affect how Vercel handles fallback: false in nested routes? How can I maintain consistent behavior across environments?

Edit) This also seems to apply when using the App Router under a similar route setup

There’s another community post with 404 debugging tips that might be helpful. Please give these solutions a try and let us know how it goes.

A human should be around soon to offer more advice. But you can also get helpful information quickly by asking v0.

Upgrading to Next > 15.4.1 solved parts of this issue. When direct navigating to a non-existant product page, the catchall route is properly executed :tada:. Though - when linking to that same page from somewhere in the application using the Next Link component - we can see that the product pages page template is trying to execute causing an error when clicking it. Refreshing the page when the error page is shown makes the proper page to be rendered

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.