diff --git a/surfsense_backend/app/routes/new_chat_routes.py b/surfsense_backend/app/routes/new_chat_routes.py index 53e6c8e09..11a8abeae 100644 --- a/surfsense_backend/app/routes/new_chat_routes.py +++ b/surfsense_backend/app/routes/new_chat_routes.py @@ -635,8 +635,16 @@ async def delete_thread( # For PRIVATE threads, only the creator can delete # For SEARCH_SPACE threads, any member with permission can delete + # Legacy threads (created_by_id is NULL) have no recorded creator, + # so we skip strict ownership and fall through to legacy handling + # which allows the search space owner to delete them if db_thread.visibility == ChatVisibility.PRIVATE: - await check_thread_access(session, db_thread, user, require_ownership=True) + await check_thread_access( + session, + db_thread, + user, + require_ownership=(db_thread.created_by_id is not None), + ) await session.delete(db_thread) await session.commit() diff --git a/surfsense_web/hooks/use-comments-electric.ts b/surfsense_web/hooks/use-comments-electric.ts index b90f52dce..6ca7748b5 100644 --- a/surfsense_web/hooks/use-comments-electric.ts +++ b/surfsense_web/hooks/use-comments-electric.ts @@ -393,11 +393,19 @@ export function useCommentsElectric(threadId: number | null) { } if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe(); + try { + liveQueryRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } }; diff --git a/surfsense_web/hooks/use-connectors-electric.ts b/surfsense_web/hooks/use-connectors-electric.ts index 08ef0621d..951f1d15a 100644 --- a/surfsense_web/hooks/use-connectors-electric.ts +++ b/surfsense_web/hooks/use-connectors-electric.ts @@ -180,11 +180,19 @@ export function useConnectorsElectric(searchSpaceId: number | string | null) { syncKeyRef.current = null; if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe(); + try { + liveQueryRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } }; diff --git a/surfsense_web/hooks/use-documents.ts b/surfsense_web/hooks/use-documents.ts index 6060b9572..e3a315cd1 100644 --- a/surfsense_web/hooks/use-documents.ts +++ b/surfsense_web/hooks/use-documents.ts @@ -230,11 +230,19 @@ export function useDocuments( async function setupElectricRealtime() { // Cleanup previous subscriptions if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe?.(); + try { + liveQueryRef.current.unsubscribe?.(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } @@ -420,11 +428,19 @@ export function useDocuments( return () => { mounted = false; if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe?.(); + try { + liveQueryRef.current.unsubscribe?.(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } }; diff --git a/surfsense_web/hooks/use-inbox.ts b/surfsense_web/hooks/use-inbox.ts index 56ddb46a4..b66f75a3a 100644 --- a/surfsense_web/hooks/use-inbox.ts +++ b/surfsense_web/hooks/use-inbox.ts @@ -129,11 +129,15 @@ export function useInbox( // Skip if already syncing with this key if (userSyncKeyRef.current === userSyncKey) return; - // Clean up previous sync - if (syncHandleRef.current) { + // Clean up previous sync + if (syncHandleRef.current) { + try { syncHandleRef.current.unsubscribe(); - syncHandleRef.current = null; + } catch { + // PGlite may already be closed during cleanup } + syncHandleRef.current = null; + } console.log("[useInbox] Starting sync for:", userId); userSyncKeyRef.current = userSyncKey; @@ -174,7 +178,11 @@ export function useInbox( mounted = false; userSyncKeyRef.current = null; if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } }; @@ -199,7 +207,11 @@ export function useInbox( async function setupLiveQuery() { // Clean up previous live query if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe(); + try { + liveQueryRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } @@ -297,7 +309,11 @@ export function useInbox( return () => { mounted = false; if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe(); + try { + liveQueryRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } }; diff --git a/surfsense_web/hooks/use-messages-electric.ts b/surfsense_web/hooks/use-messages-electric.ts index e8c82e92b..728503de9 100644 --- a/surfsense_web/hooks/use-messages-electric.ts +++ b/surfsense_web/hooks/use-messages-electric.ts @@ -142,11 +142,19 @@ export function useMessagesElectric( syncKeyRef.current = null; if (syncHandleRef.current) { - syncHandleRef.current.unsubscribe(); + try { + syncHandleRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } syncHandleRef.current = null; } if (liveQueryRef.current) { - liveQueryRef.current.unsubscribe(); + try { + liveQueryRef.current.unsubscribe(); + } catch { + // PGlite may already be closed during cleanup + } liveQueryRef.current = null; } };