From 2390bd7d269fafa40208fd88ca79bc8e8ce9eb20 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:24:41 +0530 Subject: [PATCH] feat: enhance Google Drive authentication error handling - Improved error handling for Google Drive indexing and listing operations to manage authentication failures more effectively. - Added logic to mark connectors as 'auth_expired' when a 401 error or invalid credentials are detected, prompting users to re-authenticate. - Updated error messages to provide clearer guidance on authentication issues, ensuring a better user experience. --- .../app/routes/composio_routes.py | 13 ++++++++++++ .../routes/search_source_connectors_routes.py | 3 +++ .../google_drive_indexer.py | 20 ++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/surfsense_backend/app/routes/composio_routes.py b/surfsense_backend/app/routes/composio_routes.py index 721bd458e..cbafc46c6 100644 --- a/surfsense_backend/app/routes/composio_routes.py +++ b/surfsense_backend/app/routes/composio_routes.py @@ -734,6 +734,19 @@ async def list_composio_drive_folders( raise except Exception as e: logger.error(f"Error listing Composio Drive contents: {e!s}", exc_info=True) + error_lower = str(e).lower() + if "401" in str(e) or "invalid credentials" in error_lower or "autherror" in error_lower or "authentication failed" in error_lower: + try: + if connector and not connector.config.get("auth_expired"): + connector.config = {**connector.config, "auth_expired": True} + flag_modified(connector, "config") + await session.commit() + logger.info(f"Marked Composio connector {connector_id} as auth_expired") + except Exception: + logger.warning(f"Failed to persist auth_expired for connector {connector_id}", exc_info=True) + raise HTTPException( + status_code=400, detail="Google Drive authentication expired. Please re-authenticate." + ) from e raise HTTPException( status_code=500, detail=f"Failed to list Drive contents: {e!s}" ) from e diff --git a/surfsense_backend/app/routes/search_source_connectors_routes.py b/surfsense_backend/app/routes/search_source_connectors_routes.py index 8b2209cc8..68bd650f4 100644 --- a/surfsense_backend/app/routes/search_source_connectors_routes.py +++ b/surfsense_backend/app/routes/search_source_connectors_routes.py @@ -2427,6 +2427,9 @@ async def run_google_drive_indexing( logger.error( f"Google Drive indexing completed with errors for connector {connector_id}: {error_message}" ) + if _is_auth_error(error_message): + await _persist_auth_expired(session, connector_id) + error_message = "Google Drive authentication expired. Please re-authenticate." else: # Update notification to storing stage if notification: diff --git a/surfsense_backend/app/tasks/connector_indexers/google_drive_indexer.py b/surfsense_backend/app/tasks/connector_indexers/google_drive_indexer.py index 276be8cc3..96083e5b8 100644 --- a/surfsense_backend/app/tasks/connector_indexers/google_drive_indexer.py +++ b/surfsense_backend/app/tasks/connector_indexers/google_drive_indexer.py @@ -517,6 +517,7 @@ async def _index_full_scan( # Queue of folders to process: (folder_id, folder_name) folders_to_process = [(folder_id, folder_name)] + first_listing_error: str | None = None logger.info("Phase 1: Collecting files and creating pending documents") @@ -536,6 +537,8 @@ async def _index_full_scan( if error: logger.error(f"Error listing files in {current_folder_name}: {error}") + if first_listing_error is None: + first_listing_error = error break if not files: @@ -581,6 +584,15 @@ async def _index_full_scan( if not page_token: break + if not files_to_process and first_listing_error: + error_lower = first_listing_error.lower() + if "401" in first_listing_error or "invalid credentials" in error_lower or "authError" in first_listing_error: + raise Exception( + f"Google Drive authentication failed. Please re-authenticate. " + f"(Error: {first_listing_error})" + ) + raise Exception(f"Failed to list Google Drive files: {first_listing_error}") + # Commit all pending documents - they all appear in UI now if new_documents_created: logger.info( @@ -666,7 +678,13 @@ async def _index_with_delta_sync( if error: logger.error(f"Error fetching changes: {error}") - return 0, 0 + error_lower = error.lower() + if "401" in error or "invalid credentials" in error_lower or "authError" in error: + raise Exception( + f"Google Drive authentication failed. Please re-authenticate. " + f"(Error: {error})" + ) + raise Exception(f"Failed to fetch Google Drive changes: {error}") if not changes: logger.info("No changes detected since last sync")