"use client";
import { useEffect } from "react";
/**
* The last resort: a render that threw all the way out.
*
* `BugReporter`'s window listeners do not see errors React caught, so this
* boundary reports them itself. It also has to say something true to the
* person looking at it — a blank page after a crash is the worst of both,
* since they learn nothing and neither does anyone else.
*/
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
void fetch("/api/telemetry/bug", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: error.message || "render threw",
stack: error.stack,
pathname: window.location.pathname,
kind: "boundary",
}),
keepalive: true,
}).catch(() => {
/* reporting a bug must never itself become one */
});
}, [error]);
return (
<html lang="en">
<body style={{ margin: 0 }}>
<div style={{ maxWidth: 560, margin: "18vh auto", padding: "0 24px" }}>
<h1 style={{ fontSize: 22, fontWeight: 500 }}>This screen broke.</h1>
<p style={{ lineHeight: 1.65, opacity: 0.75 }}>
The failure has been reported. Nothing you did was lost — this
surface holds everything in memory for the life of the server
process, and that process is still running.
</p>
<p
style={{
fontFamily: "ui-monospace, SF Mono, Menlo, monospace",
fontSize: 12.5,
opacity: 0.6,
wordBreak: "break-word",
}}
>
{error.message}
{error.digest ? ` · ${error.digest}` : ""}
</p>
<button
type="button"
onClick={reset}
style={{
marginTop: 14,
padding: "8px 18px",
borderRadius: 999,
border: "1px solid currentColor",
background: "transparent",
color: "inherit",
cursor: "pointer",
}}
>
Try again
</button>
</div>
</body>
</html>
);
}