Describe the bug
when deploying to cloudflare we get this warning.
Parsed 0 valid redirect rules.
2026-06-01T08:49:01.378743Z Found invalid redirect lines:
2026-06-01T08:49:01.378799Z - #1: /* /index.html 200
2026-06-01T08:49:01.378843Z Infinite loop detected in this rule and has been ignored. This will cause a redirect to strip .html or /index and end up triggering this rule again. Please fix or remove this rule to silence this warning.
With ssr: false + preset: "cloudflare_pages", Nitro auto-generates a _redirects file in the build output containing:
This is the standard SPA fallback rule. However, Cloudflare Pages recently added loop detection: since Cloudflare automatically strips .html extensions from URLs, a request to /index.html becomes /index or / → which matches /* again → infinite loop. Cloudflare now rejects this rule entirely, meaning direct navigation to any sub-route on your deployed app will 404.
I am not sure if this to be resolved in Nitro or here, but I wonder if there is better solution than this:
Temporary Fix
Use Cloudflare Pages' native 200.html SPA fallback. When 200.html exists in your output, Cloudflare serves it for all unmatched routes without the loop issue, no redirect rule needed.
Add a hooks section to your nuxt.config.ts:
export default defineNuxtConfig({
// ...existing config...
hooks: {
async 'nitro:build:public-assets'(nitro) {
const { readFileSync, writeFileSync, copyFileSync, existsSync } = await import('node:fs')
const { join } = await import('node:path')
const outDir = nitro.options.output.publicDir
// Copy index.html → 200.html so Cloudflare uses it as the SPA catch-all
const indexPath = join(outDir, 'index.html')
if (existsSync(indexPath)) {
copyFileSync(indexPath, join(outDir, '200.html'))
}
// Remove the now-invalid /* /index.html 200 rule
const redirectsPath = join(outDir, '_redirects')
if (existsSync(redirectsPath)) {
const cleaned = readFileSync(redirectsPath, 'utf-8')
.split('\n')
.filter(line => !line.startsWith('/* /index.html'))
.join('\n')
writeFileSync(redirectsPath, cleaned)
}
},
},
})
The nitro:build:public-assets hook runs after Nitro compiles and writes its output, so the modifications happen after Nitro's own _redirects is generated, no race condition.
Describe the bug
when deploying to cloudflare we get this warning.
With ssr: false + preset: "cloudflare_pages", Nitro auto-generates a _redirects file in the build output containing:
This is the standard SPA fallback rule. However, Cloudflare Pages recently added loop detection: since Cloudflare automatically strips .html extensions from URLs, a request to /index.html becomes /index or / → which matches /* again → infinite loop. Cloudflare now rejects this rule entirely, meaning direct navigation to any sub-route on your deployed app will 404.
I am not sure if this to be resolved in Nitro or here, but I wonder if there is better solution than this:
Temporary Fix
Use Cloudflare Pages' native 200.html SPA fallback. When 200.html exists in your output, Cloudflare serves it for all unmatched routes without the loop issue, no redirect rule needed.
Add a hooks section to your nuxt.config.ts:
The nitro:build:public-assets hook runs after Nitro compiles and writes its output, so the modifications happen after Nitro's own _redirects is generated, no race condition.