Most Next.js applications handle the happy path well. A request comes in, data loads, components render, user sees the page. Error handling is where applications often reveal their real quality — and where App Router introduces some nuances worth understanding.

Here's how error boundaries work in App Router, what the error.js file actually does, and the patterns that make failure handling feel intentional rather than afterthought. This is the approach I use in production for a free AI image generator for beginners where graceful degradation matters more than on sites with simpler data flows.

What Changes in App Router

Pages Router had _error.js and getInitialProps for error handling. App Router introduces a different model built on React's Error Boundary concept, with error.js files that can be nested at any level of the route hierarchy.

The key mental model shift: errors are contained at the nearest error.js boundary, not propagated to a global handler. This means you can have different error UIs for different sections of your app.