From 41442c94ab8ec84112c28c99f4bd011c802b71d7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 18 Jul 2026 23:38:06 +0800 Subject: [PATCH 1/3] fix(app): prevent notification crash on unavailable server --- packages/app/src/context/notification.tsx | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx index e12f8f1250ea..ad0395b552e5 100644 --- a/packages/app/src/context/notification.tsx +++ b/packages/app/src/context/notification.tsx @@ -124,20 +124,43 @@ export const { use: useNotification, provider: NotificationProvider } = createSi const owner = getOwner() const states = new Map void; state: NotificationState }>() + const EMPTY: NotificationState = { + ready: () => false, + session: { + all: () => [], + unseen: () => [], + unseenCount: () => 0, + unseenHasError: () => false, + markViewed: () => {}, + }, + project: { + all: () => [], + unseen: () => [], + unseenCount: () => 0, + unseenHasError: () => false, + markViewed: () => {}, + }, + } + const activeServer = createMemo(() => { if (params.serverKey) return requireServerKey(params.serverKey) if (search.draftId) { const draft = tabs.store.find((tab): tab is DraftTab => tab.type === "draft" && tab.draftID === search.draftId) if (draft) return draft.server } - return server.key + const key = server.key + const servers = global.servers.list() + if (servers.length > 0 && !servers.some((c) => ServerConnection.key(c) === key)) { + return ServerConnection.key(servers[0]) + } + return key }) const activeDirectory = createMemo(() => decode64(params.dir)) const activeSession = createMemo(() => params.id) const ensure = (key: ServerConnection.Key) => { const conn = global.servers.list().find((item) => ServerConnection.key(item) === key) - if (!conn) throw new Error(`Notification server not found: ${key}`) + if (!conn) return EMPTY const ctx = global.ensureServerCtx(conn) const existing = states.get(ctx.sdk.scope) if (existing) return existing.state From 5c31db616dccdb1d79e33b845c33e8cafb3c40fb Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 19 Jul 2026 15:26:48 +0800 Subject: [PATCH 2/3] fix(app): type notification fallback resource --- packages/app/src/context/notification.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx index ad0395b552e5..02409eb4e4f9 100644 --- a/packages/app/src/context/notification.tsx +++ b/packages/app/src/context/notification.tsx @@ -125,7 +125,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi const states = new Map void; state: NotificationState }>() const EMPTY: NotificationState = { - ready: () => false, + ready: Object.assign(() => false, { promise: undefined }), session: { all: () => [], unseen: () => [], From 4d08afe8db839497cfde0cf3fe0f8643a36119da Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 19 Jul 2026 17:28:58 +0800 Subject: [PATCH 3/3] fix(app): prevent permission crash on unavailable server --- packages/app/src/context/permission.tsx | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/app/src/context/permission.tsx b/packages/app/src/context/permission.tsx index 496d1ab4a282..7a5c86c8e55e 100644 --- a/packages/app/src/context/permission.tsx +++ b/packages/app/src/context/permission.tsx @@ -71,12 +71,37 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple const activeServer = createMemo(() => { if (params.serverKey && settings.general.newLayoutDesigns()) return requireServerKey(params.serverKey) - return activeDraft()?.server ?? server.key + const key = activeDraft()?.server ?? server.key + const servers = global.servers.list() + if (servers.length > 0 && !servers.some((s) => ServerConnection.key(s) === key)) { + return ServerConnection.key(servers[0]) + } + return key }) + const EMPTY_API = { + ready: () => true, + respond: () => {}, + autoResponds: () => false, + isAutoAccepting: () => false, + isAutoAcceptingDirectory: () => false, + toggleAutoAccept: () => {}, + toggleAutoAcceptDirectory: () => {}, + enableAutoAccept: () => {}, + disableAutoAccept: () => {}, + isPermissionAllowAll: () => false, + } + const EMPTY: PermissionState = { + ...EMPTY_API, + api: EMPTY_API, + sync: null as never, + enableConfiguredDirectory: () => {}, + permissionsEnabled: () => false, + } + const ensure = (key: ServerConnection.Key) => { const conn = global.servers.list().find((item) => ServerConnection.key(item) === key) - if (!conn) throw new Error(`Permission server not found: ${key}`) + if (!conn) return EMPTY const ctx = global.ensureServerCtx(conn) const existing = states.get(ctx.sdk.scope) if (existing && global.servers.list().some((item) => ServerConnection.key(item) === existing.key)) {