diff --git a/src/app/(inbox)/email/[id]/error.tsx b/src/app/(inbox)/email/[id]/error.tsx
new file mode 100644
index 0000000..53a2efe
--- /dev/null
+++ b/src/app/(inbox)/email/[id]/error.tsx
@@ -0,0 +1,18 @@
+"use client";
+
+export default function EmailError() {
+ return (
+
+
+
+
+ Unable to load this email
+
+
+ There was a problem fetching this email from the server. Refresh to try again.
+
+
+
+
+ );
+}
diff --git a/src/app/(inbox)/layout.tsx b/src/app/(inbox)/layout.tsx
index f97dd93..100d9bb 100644
--- a/src/app/(inbox)/layout.tsx
+++ b/src/app/(inbox)/layout.tsx
@@ -12,27 +12,57 @@ export default async function InboxLayout({
children: React.ReactNode;
}) {
const t = Date.now();
- const session = await getSession();
- const accountId = getAccountId(session);
- const mailboxes = await getMailboxes(session.apiUrl, accountId);
+
+ let session, accountId, mailboxes;
+ try {
+ session = await getSession();
+ accountId = getAccountId(session);
+ mailboxes = await getMailboxes(session.apiUrl, accountId);
+ } catch (err) {
+ log.error({ err, duration_ms: Date.now() - t }, "layout.inbox.session_error");
+ return (
+
+
+
+ Unable to connect to mail server
+
+
+ Check your connection and refresh to try again.
+
+
+
+ );
+ }
+
const inbox = mailboxes.find((m) => m.role === "inbox");
const draftsMailbox = mailboxes.find((m) => m.role === "drafts");
const sentMailbox = mailboxes.find((m) => m.role === "sent");
const archiveMailbox = mailboxes.find((m) => m.role === "archive");
const trashMailbox = mailboxes.find((m) => m.role === "trash");
- const [inbox_emails, drafts, pinned, sentResult] = await Promise.all([
- inbox
- ? listInboxEmails(session.apiUrl, accountId, inbox.id)
- : Promise.resolve({ unreads: [], unreadTotal: 0, reads: [], readTotal: 0 }),
- draftsMailbox
- ? listDrafts(session.apiUrl, accountId, draftsMailbox.id)
- : Promise.resolve([]),
- listPinnedEmails(session.apiUrl, accountId),
- sentMailbox
- ? listSentEmails(session.apiUrl, accountId, sentMailbox.id)
- : Promise.resolve({ emails: [], total: 0 }),
- ]);
+ let inbox_emails = { unreads: [] as Awaited>["unreads"], unreadTotal: 0, reads: [] as Awaited>["reads"], readTotal: 0 };
+ let drafts: Awaited> = [];
+ let pinned: Awaited> = [];
+ let sentResult: Awaited> = { emails: [], total: 0 };
+
+ try {
+ [inbox_emails, drafts, pinned, sentResult] = await Promise.all([
+ inbox
+ ? listInboxEmails(session.apiUrl, accountId, inbox.id)
+ : Promise.resolve({ unreads: [], unreadTotal: 0, reads: [], readTotal: 0 }),
+ draftsMailbox
+ ? listDrafts(session.apiUrl, accountId, draftsMailbox.id)
+ : Promise.resolve([]),
+ listPinnedEmails(session.apiUrl, accountId),
+ sentMailbox
+ ? listSentEmails(session.apiUrl, accountId, sentMailbox.id)
+ : Promise.resolve({ emails: [], total: 0 }),
+ ]);
+ } catch (err) {
+ log.error({ err, duration_ms: Date.now() - t }, "layout.inbox.fetch_error");
+ // Fall through with empty data — the panel will render with a refresh prompt
+ }
+
const { unreads, unreadTotal, reads, readTotal } = inbox_emails;
log.info({
diff --git a/src/app/(inbox)/thread/[threadId]/error.tsx b/src/app/(inbox)/thread/[threadId]/error.tsx
new file mode 100644
index 0000000..f6725aa
--- /dev/null
+++ b/src/app/(inbox)/thread/[threadId]/error.tsx
@@ -0,0 +1,18 @@
+"use client";
+
+export default function ThreadError() {
+ return (
+
+
+
+
+ Unable to load this thread
+
+
+ There was a problem fetching this email from the server. Refresh to try again.
+
+
+
+
+ );
+}