Course outline

Next.js / Intermediate: authority, freshness and route experience / Lesson 11

Loading, Suspense, error and not-found boundaries

Place progressive loading and failure UI around real data dependencies without hiding authorization or source uncertainty.

About 4 min readContent reviewed
On this page

Lesson goals

  • Distinguish loading fallbacks, expected domain results and uncaught render errors.
  • Explain segment boundary scope and late streaming limitations.

A fallback describes waiting, not completed correctness

Suspense lets a route show a fallback while nested work is pending. loading.tsx supplies a segment loading UI under the framework’s conventions. Place boundaries around meaningful independent regions so a slow recommendation does not unnecessarily block a useful authorized course title. Streaming improves time to usable UI but does not bound source fanout or make missing permission data safe to ignore. A fallback must not disclose private structure before access is established. Keep authorization and source validity in the data boundary, then decide which remaining descriptive regions can load independently.

Provide a narrow retry surface for an actual error boundary

The fragment represents a segment error.tsx Client Component with a reset callback. It deliberately does not print the raw error or digest into public UI. Imports, file placement and runtime behavior are assumed. Reset attempts to recover the boundary; it cannot guarantee the source recovered or that a failed mutation should be repeated. Segment errors do not catch every error in the application, including their own layout scope or event-handler work in the same way. Choose a parent/global boundary or explicit event error handling according to the documented lifecycle.

tsx Illustrative segment error UI
"use client";
export default function ErrorView({reset}:{error:Error & {digest?:string};reset:()=>void}) {
  return <section><h2>Course unavailable</h2><button onClick={() => reset()}>Try again</button></section>;
}

The fragment exposes safe text and a boundary retry. It was not rendered and does not prove error capture or recovery.

Model expected absence and validation separately

Expected form problems or workflow conflicts can be returned as typed application state rather than thrown as unexpected render failures. notFound and redirect use framework control flow; do not swallow them in a broad catch that changes their meaning. A not-found state should follow the application’s disclosure rule for absent or denied objects. Once streaming commits a response, later failure or not-found handling cannot freely rewrite the already-sent status and headers. Review actual HTTP and metadata behavior as well as visible UI, especially when crawlers or API clients depend on those signals.

Keep view states distinct in local logic

The local classifier distinguishes loading, unavailable source and a ready card. It never converts an unavailable permission/data source into a successful empty card. Its priority order is an explicit lab policy: an error takes precedence over an old retained record. A different view may allow stale descriptive data with a clear warning, but that must be documented. This model is not React Suspense and does not throw promises or exercise error boundaries. It tests a small presentation decision before a real component integration adds lifecycle and accessibility behavior.

javascript Complete offline view-state classifier
function viewState({pending,error,card}) {
  if (error) return "unavailable";
  if (pending) return "loading";
  return card ? "ready" : "not-found";
}
console.assert(viewState({pending:true,error:null,card:null}) === "loading");
console.assert(viewState({pending:false,error:"source",card:{id:"c1"}}) === "unavailable");
console.assert(viewState({pending:false,error:null,card:{id:"c1"}}) === "ready");

The three fixtures follow the declared priority. No streaming, Suspense or React error dispatch is performed.

Test boundaries where the failure actually occurs

Use separate fixtures for pending data, expected absence, denied access, uncaught server render failure, client event failure and late stream interruption. Assert safe output and preserved useful regions, plus no unauthorized source effect. A retry button should not reset unrelated user input or silently replay a committed mutation. Keep logs correlated without exposing source messages in rendered HTML. This course executes only the classifier; it does not verify loading conventions, boundary nesting, browser focus, streamed status or recovery. Those require an authorized isolated build and browser/transport integration with the selected Next and React versions.

Common errors and fixes

A loading skeleton reveals private structure

Why it happens
Fallback rendering preceded the required access decision.
How to fix it
Establish eligibility before exposing protected UI structure.
Prevent it next time
Test fallback output under denied principals.

A segment boundary misses its own layout error

Why it happens
Boundary scope was assumed broader than its documented placement.
How to fix it
Use the appropriate parent/global boundary and retained fixtures.
Prevent it next time
Test errors at each relevant nesting level.

Retry repeats a committed action

Why it happens
Render recovery was confused with safe business replay.
How to fix it
Reconcile the operation before any mutation retry.
Prevent it next time
Keep render failures and uncertain-write fixtures separate.

Check your understanding

1. Does reset prove that the failed source is healthy again?

Show worked solution

No. It asks the boundary to try rendering again. The source may fail repeatedly, and the earlier business effect may already exist if a mutation was involved. Test source recovery separately and preserve operation identity for writes. Keep the retry UI safe without claiming a successful network or transaction outcome.

2. Why can a visible not-found page differ from a simple pre-response 404?

Show worked solution

Streaming may have already committed headers before the absence is discovered. The framework cannot rewrite bytes already delivered as if no response began. Verify the selected framework’s status and metadata behavior with an actual transport fixture rather than inferring it from the rendered message alone.

Key takeaways

  • Loading and error boundaries follow real data and nesting dependencies.
  • Visible recovery UI does not establish source or write recovery.

Official references