Skip to content

[vite-plugin] Surface prerender response-body streaming errors#14326

Open
mikepage wants to merge 2 commits into
cloudflare:mainfrom
mikepage:feat/vite-plugin-surface-prerender-stream-errors
Open

[vite-plugin] Surface prerender response-body streaming errors#14326
mikepage wants to merge 2 commits into
cloudflare:mainfrom
mikepage:feat/vite-plugin-surface-prerender-stream-errors

Conversation

@mikepage

@mikepage mikepage commented Jun 16, 2026

Copy link
Copy Markdown

Adds an opt-in experimental.bufferPreviewResponses option to the Cloudflare Vite plugin that surfaces response-body streaming errors during vite preview.

Problem

When a Worker returns a streaming Response and the body stream errors after the 200 status and headers have been committed (for example a component that throws mid-render during framework prerendering), workerd terminates the chunked response cleanly. The HTTP consumer sees a successful but silently-truncated 200 with no error — so astro build–style prerendering writes truncated HTML and exits 0. The underlying runtime behaviour is tracked upstream in cloudflare/workerd#6818; downstream report: withastro/astro#17047.

Change

When experimental.bufferPreviewResponses is enabled, the preview Worker's entry is wrapped so its response body is fully buffered in-worker (the only place the stream error is catchable). A buffered body error — or any thrown handler error — is returned as a 500 carrying an x-vite-cloudflare-worker-error marker header.

  • The marker is set on the Worker's own response, so it reliably traverses the proxy and preview server back to the caller (a thrown dispatchFetch would otherwise be swallowed/reshaped by the proxy and lose custom headers).
  • It lets consumers (e.g. a framework's prerenderer) distinguish a thrown error from a response the Worker intentionally returned with a non-2xx status (a custom 404 still passes through unchanged).
  • Off by default — buffering breaks legitimate streaming responses in a normal preview.
  • The wrapper re-exports named exports (Durable Objects, entrypoints, Workflows) and non-fetch handlers; it assumes a plain-object default export.

The companion @astrojs/cloudflare change (separate repo) enables this option and consumes the marker header.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because:
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: the option is experimental and consumed by framework adapters (e.g. @astrojs/cloudflare) rather than used directly; it can be documented when/if stabilised.

Open in Devin Review

Add an opt-in `experimental.bufferPreviewResponses` option. When enabled,
the preview Worker's entry is wrapped so its response body is fully
buffered in-worker. A body stream that errors after headers are committed
(e.g. a component throwing mid-render during prerendering) — which workerd
otherwise terminates as a silently-truncated 200 — is caught and returned
as a 500 carrying an `x-vite-cloudflare-worker-error` marker header.

The marker is set on the Worker's own response so it reliably traverses
the proxy and preview server back to the caller, and lets consumers (e.g.
a framework's prerenderer) distinguish a thrown error from a response the
Worker intentionally returned with a non-2xx status. Off by default, since
buffering breaks legitimate streaming responses in a normal preview.

The wrapper re-exports named exports (Durable Objects, entrypoints,
Workflows) and non-fetch handlers, and assumes a plain-object default
export.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 280b5ac

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/vite-plugin Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@workers-devprod workers-devprod requested review from a team and ascorbic and removed request for a team June 16, 2026 14:47
@workers-devprod

Copy link
Copy Markdown
Contributor

Codeowners approval required for this PR:

  • @cloudflare/wrangler
Show detailed file reviewers
  • .changeset/cuddly-pillows-buffer.md: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/tests/fixtures/streaming-error/index.ts: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/tests/fixtures/streaming-error/wrangler.jsonc: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/tests/preview-stream-errors.spec.ts: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/miniflare-options.ts: [@cloudflare/wrangler]
  • packages/vite-plugin-cloudflare/src/plugin-config.ts: [@cloudflare/wrangler]

devin-ai-integration[bot]

This comment was marked as resolved.

… Workers

Scope `bufferPreviewResponses` to the request dispatch target (the first
Worker) so auxiliary/service-bound Workers keep their normal streaming
behaviour, rather than wrapping every Worker in the preview.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants