Error.tsx en Next.js App Router: captura de errores por segmento con ejemplos y salida esperada
Introducción
Cuando trabajás con el App Router de Next.js (versión 13+), el manejo de errores cambió respecto al modelo clásico de pages. Ahora tenés la posibilidad de definir límites de error (error boundaries) a nivel de segmento de ruta mediante el archivo especial error.tsx. Este mecanismo permite que, si algo falla en una página, layout o componente hijo, la aplicación muestre una UI de fallback específica en lugar de romper toda la página o mostrar un error genérico de 500.
Este artículo está dirigido a desarrolladores que ya manejan los conceptos básicos de Next.js y quieren profundizar en el manejo robusto de errores dentro del nuevo modelo de rutas. Al finalizar, vas a saber:
- Qué es
error.tsxy dónde colocarlo. - Cómo los errores se propagan hacia arriba por el árbol de segmentos.
- Cómo personalizar la UI de error según el segmento donde ocurrió.
- Qué información tenés disponible dentro del componente error`) y notificar errores a servicios de monitoreado y cómo usarla.
- Buenas prácticas y errores comunes al implementar límites de error.
Vamos a ver ejemplos completos, con el código de los archivos y la salida esperada que vería el usuario en el navegador.
1. ¿Cómo funciona el App Router y los límites de error?
En el App Router, cada segmento de ruta (una carpeta dentro de app/) puede contener archivos especiales:
page.tsx→ la página que se renderiza para ese segmento.layout.tsx→ layout que envía a las páginas hijas.loading.tsx→ UI de suspense mientras se cargan datos.not-found.tsx→ UI para rutas inexistentes (404).error.tsx→ límite de error que captura excepciones lanzadas por cualquier hijo (page, layout, componentes, etc.) dentro de ese segmento.
Cuando se lanza un error dentro de un segmento, Next.js busca el archivo error.tsx más cercano en el árbol de rutas, empezando por el segmento donde ocurrió y subiendo hacia la raíz. Si no encuentra ninguno, se muestra el error de desarrollo (stack trace) o, en producción, una página de error genérica 500.
Esto brinda un gran poder: podés tener un error.tsx global que maneje errores de toda la aplicación, y, a la vez, definir límites más específicos para secciones críticas (por ejemplo, un panel de admin o un carrito de compras).
2. Estructura básica de error.tsx
El archivo error.tsx debe exportar un componente React por defecto que reciba dos props:
error: la instancia del error que fue lanzada.reset: una función que, al ser llamada, intenta volver a renderizar el segmento hijo (útil para errores transitorios).
Un ejemplo mínimo se ve así:
// app/error.tsx
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div>
<h2>Algo salió mal</h2>
<p>{error.message}</p>
<button onClick={reset}>Intentar de nuevo</button>
</div>
);
}Nota: el tipo de error incluye una propiedad opcional digest que Next.js usa en producción para identificar el error sin exponer detalles sensibles.
3. Primer ejemplo: error en una página simple
Vamos a crear una ruta /demo que intencionalmente lanza un error. La estructura de archivos será:
app/
├── demo/
│ ├── page.tsx
│ └── error.tsx
└── error.tsx // límite global (opcional)3.1. app/demo/page.tsx
// app/demo/page.tsx
export default function DemoPage() {
// Simulamos un error al renderizar
throw new Error('Error intencional en la página demo');
return <p>Este contenido nunca se verá</p>;
}3.2. app/demo/error.tsx
// app/demo/error.tsx
export default function DemoError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div style={{ padding: '2rem', fontFamily: 'system-ui, sans-serif' }}>
<h1 style={{ color: '#d32f2f' }}>Error en la sección demo</h1>
<p>{error.message}</p>
<button onClick={reset} style={{ marginTop: '1rem', padding: '0.5rem 1rem' }}>
Volver a intentar
</button>
</div>
);
}3.3. Salida esperada en el navegador
Al visitar http://localhost:3000/demo, verás:
- Un encabezado rojo "Error en la sección demo\
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.