Skip to content

x-void-page-data header causes fetch failed for pages with large props #19

Closed

Description

@hyfdev

Summary

The x-void-page-data response header (added in 636c71d) serializes the entire PageObject via JSON.stringify(pageObj) into an HTTP response header on every non-deferred SSR HTML response. For pages with large props, this exceeds HTTP header size limits and causes fetch failed errors.

Reproduction

  • Branch: fix/x-void-page-data-large-props — adds a playground page (large-props) generating ~300KB of props and a failing integration test test: reproduce x-void-page-data header failure with large props #20
  • Run: pnpm test:pages:react-vue -- -t "SSG prerender should not fail" --hookTimeout=60000
  • Result: prerender /large-props failed: fetch failed

Real-world impact

A Notion-powered blog (musubi) where each page returns:

  • ExtendedRecordMap (~30-70KB) — Notion page data for client-side React hydration
  • Pre-rendered HTML (~50-200KB) — server-rendered Notion content

All 16 blog post pages fail with fetch failed during vite build with output: "static". The header also causes 500 errors in dev mode when props contain non-ASCII characters (Unicode text, emoji — common in CMS data).

Root cause

packages/void/src/pages/protocol.ts:221:

return new Response(html, {
  headers: {
    "content-type": "text/html; charset=utf-8",
    "x-void-page-data": JSON.stringify(pageObj), // ← entire page props in a header
    ...POWERED_BY,
  },
});

The header was added for dispatch to populate a separate JSON edge cache for SPA navigation. However:

  1. HTTP headers are not designed for large payloads — Miniflare/workerd enforces size limits, Node/undici rejects non-ASCII header values
  2. Affects all modes — SSG prerendering (via mf.dispatchFetch()), dev server (non-ASCII props), and would affect production Workers (~32KB header limit)
  3. Page data is already in the HTML — the same data is embedded in the data-page attribute, making the header redundant for rendering

Environments affected

Mode Failure
SSG prerender (output: "static") fetch failed via Miniflare
Dev server 500 error when props contain non-ASCII characters
Production Workers Would hit ~32KB Cloudflare header limit

Suggested fix

Remove the header or use an alternative mechanism for edge cache population that doesn't rely on HTTP headers (e.g., write to Cache API directly, or parse data-page from the HTML body in dispatch).

Activity

  1. hyfdev commented on Apr 14, 2026

    @hyfdev
    ContributorAuthor

    Fixed in 00bae0f by moving the page data payload from the x-void-page-data HTTP header into an inline <script id="__VOID_PAGE_DATA__" type="application/json"> tag in the HTML body. This eliminates HTTP header size limits entirely.

    The fix is solid — XSS escaping is in place (serializePageData escapes <, >, &, \u2028, \u2029), and a follow-up in 54fbd91 applied the same escaping to deferred data streams. All 4 framework adapters (React, Vue, Svelte, Solid) use the same pattern consistently. CI passes including the large-props regression test from #20.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions