You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
x-void-page-data header causes fetch failed for pages with large props #19
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.
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:
returnnewResponse(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:
HTTP headers are not designed for large payloads — Miniflare/workerd enforces size limits, Node/undici rejects non-ASCII header values
Affects all modes — SSG prerendering (via mf.dispatchFetch()), dev server (non-ASCII props), and would affect production Workers (~32KB header limit)
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).
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.
Activity
hyfdev commentedon Apr 14, 2026
Fixed in 00bae0f by moving the page data payload from the
x-void-page-dataHTTP 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 (
serializePageDataescapes<,>,&,\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.fix: reject reserved binding names in deploy manifest vars (#19)