skip to content

A deferred region of a streamed route fails after the shell was flushed. What reaches the browser, and what does the page report?

level: seniorimportance: should knowfreq 46%

answer

  1. the status was decided long ago
  2. the document cannot be replaced now
  3. nearest fallback, not the whole-page error
  4. one region degrades, the page survives
  5. a truncated stream is the worse ending

basics

~20 s

A late chunk that swaps the placeholder for the nearest error fallback, on a response that already reported success. The route's whole-page error screen is unreachable, because replacing the document would mean un-sending bytes the browser has parsed.

solid answer

~40 s

The failure happens below the commit point, so the response's status is already whatever the shell committed — typically success. The framework cannot escalate it, and it cannot render the route's whole-page error screen either, because that screen replaces the document and the document is already on the browser's screen. What it does instead is serialise the failure into the stream: a chunk that fills the failed region with the nearest error fallback declared around it, or leaves the placeholder in a failed state. The rest of the page is untouched and the other regions keep arriving. The bad case is a failure that stops the server writing at all: the response simply ends mid-document, and the browser is left with a truncated page whose pending placeholders never resolve.

go deeper

for a junior

Remember that a page which has started sending cannot change its answer. A region that fails late shows an error inside its own box while the rest of the page stays as it was.

for a middle

Explain the mechanism: the failure is serialised into the stream as a chunk that swaps the placeholder for the nearest declared fallback, on a response whose status was committed with the shell.

for a senior

Show you have seen the ugly ending — a truncated response leaving placeholders stuck forever — and that you declare a fallback around every deferred region so the framework is never the one choosing.

for a principal

Decide per region what a failure is allowed to mean: regions whose failure makes the page pointless belong above the flush, where a failure can still be the whole answer.

## Where the failure lands A deferred region's work runs after the shell has been flushed, which puts it below the response's commit point. Two things follow immediately, and candidates who have not lived through this usually miss both: - **The status is settled.** Whatever the shell committed — almost always a success status — is what this request will be recorded as, no matter what happens next. - **The document is unreplaceable.** The browser has already parsed a frame, applied styles, possibly run scripts. A whole-page error screen would have to take the place of markup the user is looking at; the response has no mechanism for that. So the framework's only remaining channel is the same one it uses for success: another chunk on the open response. ## What the framework actually sends 1. The failed region's placeholder is targeted exactly as a successful one would be. 2. In place of the finished markup, the chunk carries the **nearest error fallback** declared around that region — a scoped error UI, an empty state, or a retry affordance. 3. If no fallback is declared around it, the behaviour varies: some frameworks fall back to a generic in-region message, some leave the loading fallback on screen indefinitely, and some abort the response. 4. Other pending regions are unaffected and keep arriving; a failure in one placeholder is not a failure of the document. | what failed | what the client gets | status on the wire | |---|---|---| | a level above the flush | the route's whole-page error screen, or an error status | error status, chosen before commit | | a deferred region with a fallback around it | that fallback swapped into the placeholder | the success already committed | | a deferred region with no fallback | framework-dependent: a generic message, a stuck placeholder, or a truncated response | the success already committed | | the write itself, mid-stream | a truncated document, pending placeholders stuck | the success already committed | ## The asymmetry that surprises people The same exception thrown one level higher in the same route produces a completely different outcome: above the flush, the framework's error handling can still choose the status and render the whole-page error screen; below it, the identical failure is a cosmetic swap inside one box on an otherwise successful page. Nothing about the exception changed — only where in the chain it was raised relative to the flush. That is worth saying out loud in an interview, because it is the practical reason to be deliberate about what gets deferred. ## The truncated-response case The worse outcome is not an error fallback but no more bytes. If the failure prevents the server from writing anything further — the process dies, the connection is severed, a write times out — the response simply ends in the middle of a document. The browser has no way to distinguish that from a slow network that stopped: it keeps the partial page, the pending placeholders keep their loading fallbacks, and nothing ever resolves them. There is no error page, because the response reported success long ago. Recovery has to come from the client or from the user. This is the case worth designing against: a per-region fallback is a degraded page, while a truncated stream is a page frozen mid-load with no signal that anything went wrong. ## What the page should do about it - **Declare a fallback around every deferred region**, so the framework has somewhere to put a failure instead of choosing for you. - **Make the fallback actionable** when the region is a read — a retry control that re-requests just that region's data is cheap, and far better than asking the user to reload a page whose good parts are already correct. - **Do not defer work whose failure should have been the whole answer.** If a region failing means the page is meaningless, that work belonged above the flush where a failure could still become an error status. - **Accept that the user's judgement differs from the status code's.** The page reports success and shows a broken panel; whether that is acceptable is a product decision per region, and it is the reason some regions are held in the shell. ## Where meta-frameworks differ The fallback scoping model is not uniform: some frameworks resolve a failure to the nearest enclosing error boundary and will walk outwards if none is declared, others scope strictly to the deferred region, and a few end the response rather than guess. Confirm the behaviour for the route you own rather than assuming the shape — the difference shows up only when something fails in production.

  • What does the browser do if the response ends mid-document because of the failure?
    It keeps what it parsed. The delivered parts stay on screen, the pending placeholders keep their loading fallbacks, and nothing resolves them, because a truncated response looks the same as a stalled one. No error page can appear — success was reported with the shell — so recovery is a client-side retry or a reload by the user.
  • Should a failed region offer a retry, and what should that retry do?
    For a read, yes: a control that re-requests only that region's data recovers the page without discarding the parts that are already correct. A full reload is the blunt alternative and re-pays the whole render. For a region whose failure invalidates the page, the better fix is not retry but moving that work above the flush.
  • Why does the same exception behave differently one level higher in the route?
    Above the flush the response is uncommitted, so the framework can still choose an error status and render the route's whole-page error screen. Below it, the envelope is sent and the document is on screen, so the only channel left is a chunk that fills one placeholder. Placement, not the exception, decides the outcome.

saying these in an interview costs you the question

  • Expects the whole-page error screen to replace the streamed document
  • Thinks the framework can still escalate the status to an error
  • Assumes a failing region always ends the whole response
  • Reads a success status as proof every region rendered
  • Believes the browser detects and retries a truncated document