3d066fa67e
Deploy to VPS / deploy (push) Has been cancelled
The /en/applications/digital-print page was still 500-ing after the
previous fixes. Without an error boundary, Next.js shows a generic
"Internal Server Error" with no detail — making remote diagnosis
require a `docker compose logs` round-trip every time.
ERROR BOUNDARIES (visible diagnostics)
- src/app/global-error.tsx: catches errors that bubble past every
route's error.tsx, including ones from the root layout. Renders
its own <html>/<body>.
- src/app/[locale]/error.tsx: locale-scoped boundary so the NavBar
and Footer keep rendering around the error UI. Shows the actual
error message + digest in a code block — much faster to diagnose
than a blank 500.
DEFENSIVE WRAPPING (every async + every transform)
- applications/[slug]/page.tsx
- getApplicationImages: try/catch around fs ops
- generateMetadata: full body wrapped, falls back to safe defaults
- getLocalizedData call wrapped (returns rawData if it throws)
- Cases query already had try/catch — adds same for the locale map
- JSON-LD build wrapped, falls back to empty array (still renders)
- Default fallbacks for title/description/category to avoid
productSchema receiving undefined fields
- news/[slug]/page.tsx
- prisma.newsArticle.findUnique now has try/catch
- getLocalizedData wrapped
- JSON-LD build wrapped, only rendered if non-empty
- publishedAt / updatedAt fallback to new Date() to avoid
"Invalid time value" from articleSchema's date conversion
The combination means: if the underlying bug is in any of the SEO
helpers, JSON-LD generation, or i18n merging, the page now degrades
gracefully and shows the actual error in the UI instead of 500-ing.
79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
// Global error boundary — catches errors that bubble up past route-level
|
|
// error.tsx files. Renders its own <html>/<body> because the root layout
|
|
// errored too.
|
|
|
|
import { useEffect } from "react";
|
|
|
|
export default function GlobalError({
|
|
error,
|
|
reset,
|
|
}: {
|
|
error: Error & { digest?: string };
|
|
reset: () => void;
|
|
}) {
|
|
useEffect(() => {
|
|
console.error("[GlobalError]", error);
|
|
}, [error]);
|
|
|
|
return (
|
|
<html lang="en">
|
|
<body
|
|
style={{
|
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
background: "#0A0A0C",
|
|
color: "#F5F5F7",
|
|
minHeight: "100vh",
|
|
margin: 0,
|
|
padding: "2rem",
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
}}
|
|
>
|
|
<div style={{ maxWidth: 720, width: "100%" }}>
|
|
<h1 style={{ fontSize: 28, fontWeight: 300, marginBottom: 16 }}>
|
|
Something went wrong on FLUX
|
|
</h1>
|
|
<p style={{ color: "#86868B", marginBottom: 24 }}>
|
|
The page hit an unexpected error. The team has been notified.
|
|
</p>
|
|
|
|
<pre
|
|
style={{
|
|
background: "#1D1D1F",
|
|
padding: 16,
|
|
borderRadius: 12,
|
|
overflow: "auto",
|
|
fontSize: 12,
|
|
color: "#FF6B6B",
|
|
border: "1px solid rgba(255,255,255,0.08)",
|
|
}}
|
|
>
|
|
{error.message || "Unknown error"}
|
|
{error.digest ? `\n\nDigest: ${error.digest}` : ""}
|
|
</pre>
|
|
|
|
<button
|
|
onClick={() => reset()}
|
|
style={{
|
|
marginTop: 24,
|
|
padding: "12px 24px",
|
|
background: "#00F0FF",
|
|
color: "#000",
|
|
border: "none",
|
|
borderRadius: 8,
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: "pointer",
|
|
}}
|
|
>
|
|
Try again
|
|
</button>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|