Fix: Cannot Load Payload in Nuxt

Error message:
Cannot load payload from {url}.
ssr 2025-01-25

What Causes This Warning?

This warning appears when Nuxt cannot fetch the payload file for a pre-rendered or server-rendered page. The payload contains serialized data from useAsyncData and useFetch calls that should be rehydrated on the client.

The Problem

[warn] Cannot load payload from /_payload.json
[warn] Cannot load payload from /products/123/_payload.json

Common Causes

1. Payload File Missing

The _payload.json file wasn’t generated during build:

# Check if payload exists
ls -la .output/public/_payload.json
ls -la .output/public/products/123/_payload.json

2. Incorrect Base URL

// nuxt.config.ts
export default defineNuxtConfig({
  // ❌ Wrong base URL
  app: {
    baseURL: '/app/'  // But hosting at root
  }
})

3. CDN/Proxy Issues

The payload file is blocked or not forwarded by CDN/reverse proxy.

4. Trailing Slash Mismatch

// nuxt.config.ts
export default defineNuxtConfig({
  // Mismatch between URL structure and file locations
  routeRules: {
    '/products/**': { prerender: true }
  }
})

The Fix

Fix 1: Regenerate the Build

# Clean build
rm -rf .nuxt .output

# Rebuild
npm run build

# Check payload files
find .output/public -name "_payload.json"

Fix 2: Enable Payload Extraction

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    payloadExtraction: true
  }
})

Fix 3: Check Route Rules

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Ensure prerendered routes generate payloads
    '/products/**': {
      prerender: true
    },
    '/blog/**': {
      prerender: true
    }
  }
})

Fix 4: Configure Server/CDN

For Nginx:

location ~ /_payload\.json$ {
    add_header Cache-Control "public, max-age=3600";
    try_files $uri =404;
}

For Netlify (netlify.toml):

[[headers]]
  for = "/*/_payload.json"
  [headers.values]
    Cache-Control = "public, max-age=3600"

Fix 5: Fix Base URL

// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    baseURL: '/'  // Match your hosting setup
  }
})

Understanding Payloads

What’s in a Payload?

// _payload.json structure
{
  "data": {
    "products": [/* serialized data */]
  },
  "state": {
    "pinia": {/* store state */}
  }
}

When Payloads Are Used

  1. Pre-rendered pages: Data is extracted during build
  2. Client-side navigation: Payload is fetched instead of re-running API calls
  3. Hydration: Client uses payload to hydrate without flash

Debugging

Check Build Output

# List all payload files
find .output/public -name "_payload.json" | head -20

# Check payload content
cat .output/public/_payload.json | jq .

Check Network Tab

  1. Open DevTools → Network
  2. Navigate to a page
  3. Filter by _payload.json
  4. Check if request succeeds or fails

Verify Payload URL

<script setup>
// Debug payload URL
const nuxtApp = useNuxtApp()
onMounted(() => {
  console.log('Payload URL:', nuxtApp._payloadCache)
})
</script>

Static Generation Issues

// nuxt.config.ts
export default defineNuxtConfig({
  // For fully static sites
  ssr: true,

  nitro: {
    prerender: {
      crawlLinks: true,  // Auto-discover pages
      routes: ['/']      // Start from homepage
    }
  }
})

Generate All Routes

// nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    async 'prerender:routes'({ routes }) {
      // Fetch dynamic routes from API
      const products = await $fetch('/api/products')
      for (const product of products) {
        routes.add(`/products/${product.slug}`)
      }
    }
  }
})

Fallback Options

Disable Payload for Specific Routes

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/dynamic/**': {
      experimentalNoScripts: true  // No payload needed
    }
  }
})

Use Server Routes Instead

<script setup>
// Instead of relying on payload, fetch fresh data
const { data } = await useFetch('/api/products', {
  server: true,
  lazy: true  // Fetch on client if payload fails
})
</script>

Payload Compression

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    compressPublicAssets: {
      gzip: true,
      brotli: true
    }
  }
})

Ensure server sends compressed payloads:

location ~ /_payload\.json$ {
    gzip on;
    gzip_types application/json;
}

Quick Checklist

  • Build completed successfully with payload files
  • Base URL matches deployment configuration
  • Server/CDN serves _payload.json files correctly
  • Route rules enable prerendering for dynamic routes
  • No CORS issues blocking payload requests
  • Trailing slashes are consistent
  • Payload extraction is enabled if needed