content icon indicating copy to clipboard operation
content copied to clipboard

"content not found" on direct page refresh/navigation in production

Open Aravinda93 opened this issue 4 months ago • 10 comments

Environment

  • Operating system : macos
  • @nuxt/content: ^3.6.3
  • nuxt ^4.0.3
  • Node 24

In a Nuxt 4 project utilizing @nuxt/content, I am encountering an issue where content-rendered pages display "content not found" when directly navigating to the URL or refreshing the page with F5 in a production environment. The same pages load and render correctly when navigated via a <NuxtLink> from another page on the same site.

This issue is specific to production builds and is not reproducible in the local development environment. I am using @nuxt/content version ^3.6.3 and nuxt version ^4.0.3.

Version

v3

Reproduction

Reproducible Steps

  1. Build the Nuxt project for production (npm run build).

  2. Start the production server (npm run prod).

  3. Navigate to a content-rendered page via an internal <NuxtLink>. The content loads correctly.

  4. Perform a hard refresh (F5) on the same page. The page briefly shows the content before displaying a "content not found" message.

  5. Open a new browser tab and paste the exact URL of the content page. The page loads with "content not found" immediately.

Description

  • The problem appears to be related to Server-Side Rendering (SSR) and how the client-side hydration process handles API requests for content. The initial server-rendered HTML seems to contain the content, but the subsequent client-side fetch fails.

  • The API endpoint /api/_content returns a 404 error on page refresh or direct navigation.

  • This behavior has also been reported in related GitHub discussions, such as nuxt/content#2378. But there has not been much discussion around this in long time and it has been open since about 2 years now so wondering if this issue still in discussion and planning to fix this. Hence creating this new issue.

Additional context

Adding reference to old GitHub issue: https://github.com/nuxt/content/issues/2378

Normal navigation works fine, but when I do a hard refresh (cmd+shift+r), then for a fraction of a second I see the content, then I see the message content not found. I am seeing this issue in production only, but unable to recreate it in the local dev environment.

Any workaround or suggestion would be really helpful.

Aravinda93 avatar Sep 11 '25 16:09 Aravinda93

Could you provide a reproduction repository or online on Stackblitz?

Is this happens on your production? From your description, I think this happens because your web-server/provider adds trailing slash to URLs and it misses.

If you are using queryCollection(COLLECTION).path(route.path) try to cleanup route.path


import { withoutTrailingSlash } from 'ufo'

queryCollection(COLLECTION).path(withoutTrailingSlash(route.path))

farnabaz avatar Sep 12 '25 08:09 farnabaz

Could you also provide some information about your production environment? Where did you deploy? Did you use nuxt build or nuxt generate?

farnabaz avatar Sep 12 '25 13:09 farnabaz

@farnabaz

Many thanks for the response. I have recreated the reproduction in Codesandbox: https://codesandbox.io/p/devbox/98ht6t

If you observe that when I access the /privacy or /imprint, it works, but for some reason accessing /privacy/ or /imprint/ not work.

I used the nuxt generate to build the .output, which we deploy. I believe your first response with withoutTrailingSlash should work i feel let me try this once.

Aravinda93 avatar Sep 12 '25 14:09 Aravinda93

@farnabaz

Many thanks again for the response. It seems to be working with your suggested changes:

import { withoutTrailingSlash } from 'ufo'

queryCollection(COLLECTION).path(withoutTrailingSlash(route.path))

I tried following in my code and its working:

import { withoutTrailingSlash } from 'ufo';
  const fetchByPath = (path: string) =>
    queryCollection(collectionName).where("path", "=", withoutTrailingSlash(path)).first();

But i am observing one small issue: When I do npm run generate and run the code in preview mode using the npm run preview then during the hard refresh or opening in private mode i see that for a fraction of second i see content not found for some reason. How to avoid this? For example if you open this https://98ht6t-32781.csb.app/privacy/ and maybe refresh then you will see for a second content not found.

Example:
If you visit this page and refresh, you can see that flash for a fraction of a second:
https://98ht6t-32781.csb.app/privacy/

Reproduction

I’ve created a minimal reproduction here:
https://codesandbox.io/p/devbox/98ht6t

Question

Is this behaviour expected during hydration, or is there something in my setup I should fix to avoid the brief “content not found” state?

Aravinda93 avatar Sep 12 '25 15:09 Aravinda93

@farnabaz

When you get a chance, could you please take a look at this CodeSandbox example: https://codesandbox.io/p/devbox/98ht6t and suggest how to fix the issue?

I’ve noticed a small problem:
After running npm run generate and then serving the site with npm run preview, if I do a hard refresh or open the site in a private window, I briefly see a “Content not found” message before the correct content loads.

For example, if you open https://98ht6t-32781.csb.app/privacy/ and refresh, you should see this flash of “Content not found” for a second.

Is there a recommended way to avoid this?

Aravinda93 avatar Sep 14 '25 14:09 Aravinda93

Thanks @farnabaz for the solution! This fixed my issue as well.

I initially went down a rabbit hole thinking this was related to SQLite/WASM loading timing issues after checking out the network tab in the devtools. When I added a 2 to 10-second delay to the request, it worked fine, which reinforced my suspicion.

I ended up implementing a workaround with loading states, re-fetch logic, and exponential back-off, but this introduced an unwanted loading flash on every page refresh.

When I stumbled upon this thread, I was honestly skeptical that something as simple as a trailing slash could be the root cause. But after trying withoutTrailingSlash(route.path), it solved the issue completely.

The misleading error message really sent me down the wrong path. Hopefully this comment helps others who encounter the same issue and avoid the overly complex solutions I initially attempted!

GreenMan36 avatar Nov 03 '25 11:11 GreenMan36

I'm experiencing similar issues with github pages.

Seems fine when building locally and previewing it. But once deployed on github pages I get a brief flash of content not found. The console also shows hydration mismatch.

schplitt avatar Nov 19 '25 19:11 schplitt

I am experiencing this issue. Build works locally and fails in production env as described above in Nuxt hub cloud flare worker deployments. My Nuxt config is set to drop trailing slashes with wrangler. I also trim the trailing slash as described above. Who ever can get this resolved I am willing to put a 100$ bounty on this being resolved as it is blocking my paying work.

treygrr avatar Nov 21 '25 04:11 treygrr

Solved my issue so bounty is offline.

Issue traced to NuxtHub: I hadn’t enabled hub: { database: true } in nuxt.config.ts, so the database binding was missing—pure PEBKAC.

treygrr avatar Nov 21 '25 05:11 treygrr

Thanks @farnabaz for the solution! This fixed my issue as well.

When I stumbled upon this thread, I was honestly skeptical that something as simple as a trailing slash could be the root cause. But after trying withoutTrailingSlash(route.path), it solved the issue completely

I have the issue as well but it persists if i hardcode the path:

const { data: about } = await useAsyncData("about", () => {
  return queryCollection("markdown").path("/data/about").first();
});

It of course only happens when i first enter the page, on navigation from another page it works perfectly fine.

What fixed it for me (but ugly)

const { data: about } = await useAsyncData("about", () => {
  return queryCollection("markdown").path("/data/about").first();
}, {
  server: false
});

SaiCode-OTH avatar Dec 01 '25 12:12 SaiCode-OTH

I moved out of nuxt/content because of this bug. using server: false, just isnt a solution for SSR nuxt

AhmedSeraje avatar Dec 16 '25 20:12 AhmedSeraje