From 358af97936daa51db124728a7abd676e02d3ec59 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 5 Dec 2025 17:44:25 -0300 Subject: [PATCH 1/5] fixed error not popping up on upload --- .../_components/onboarding-upload.tsx | 590 +++++++++++------- 1 file changed, 368 insertions(+), 222 deletions(-) diff --git a/frontend/app/onboarding/_components/onboarding-upload.tsx b/frontend/app/onboarding/_components/onboarding-upload.tsx index fbb86909..749f75fd 100644 --- a/frontend/app/onboarding/_components/onboarding-upload.tsx +++ b/frontend/app/onboarding/_components/onboarding-upload.tsx @@ -1,3 +1,4 @@ +import { X } from "lucide-react"; import { AnimatePresence, motion } from "motion/react"; import { type ChangeEvent, useEffect, useRef, useState } from "react"; import { toast } from "sonner"; @@ -7,262 +8,407 @@ import { useGetTasksQuery } from "@/app/api/queries/useGetTasksQuery"; import { AnimatedProviderSteps } from "@/app/onboarding/_components/animated-provider-steps"; import { Button } from "@/components/ui/button"; import { - ONBOARDING_UPLOAD_STEPS_KEY, - ONBOARDING_USER_DOC_FILTER_ID_KEY, + ONBOARDING_UPLOAD_STEPS_KEY, + ONBOARDING_USER_DOC_FILTER_ID_KEY, } from "@/lib/constants"; import { uploadFile } from "@/lib/upload-utils"; interface OnboardingUploadProps { - onComplete: () => void; + onComplete: () => void; } const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { - const fileInputRef = useRef(null); - const [isUploading, setIsUploading] = useState(false); - const [currentStep, setCurrentStep] = useState(null); - const [uploadedFilename, setUploadedFilename] = useState(null); - const [uploadedTaskId, setUploadedTaskId] = useState(null); - const [shouldCreateFilter, setShouldCreateFilter] = useState(false); - const [isCreatingFilter, setIsCreatingFilter] = useState(false); + const fileInputRef = useRef(null); + const [isUploading, setIsUploading] = useState(false); + const [currentStep, setCurrentStep] = useState(null); + const [uploadedFilename, setUploadedFilename] = useState(null); + const [uploadedTaskId, setUploadedTaskId] = useState(null); + const [shouldCreateFilter, setShouldCreateFilter] = useState(false); + const [isCreatingFilter, setIsCreatingFilter] = useState(false); + const [error, setError] = useState(null); - const createFilterMutation = useCreateFilter(); + // Track which tasks we've already handled to prevent infinite loops + const handledFailedTasksRef = useRef>(new Set()); - const STEP_LIST = [ - "Uploading your document", - "Generating embeddings", - "Ingesting document", - "Processing your document", - ]; + const createFilterMutation = useCreateFilter(); - // Query tasks to track completion - const { data: tasks } = useGetTasksQuery({ - enabled: currentStep !== null, // Only poll when upload has started - refetchInterval: currentStep !== null ? 1000 : false, // Poll every 1 second during upload - }); + const STEP_LIST = [ + "Uploading your document", + "Generating embeddings", + "Ingesting document", + "Processing your document", + ]; - const { refetch: refetchNudges } = useGetNudgesQuery(null); + // Query tasks to track completion + const { data: tasks } = useGetTasksQuery({ + enabled: currentStep !== null, // Only poll when upload has started + refetchInterval: currentStep !== null ? 1000 : false, // Poll every 1 second during upload + }); - // Monitor tasks and call onComplete when file processing is done - useEffect(() => { - if (currentStep === null || !tasks || !uploadedTaskId) { - return; - } + const { refetch: refetchNudges } = useGetNudgesQuery(null); - // Find the task by task ID from the upload response - const matchingTask = tasks.find((task) => task.task_id === uploadedTaskId); + // Monitor tasks and call onComplete when file processing is done + useEffect(() => { + if (currentStep === null || !tasks || !uploadedTaskId) { + return; + } - // If no matching task found, wait for it to appear - if (!matchingTask) { - return; - } + // Find the task by task ID from the upload response + const matchingTask = tasks.find((task) => task.task_id === uploadedTaskId); - // Check if the matching task is still active (pending, running, or processing) - const isTaskActive = - matchingTask.status === "pending" || - matchingTask.status === "running" || - matchingTask.status === "processing"; + // If no matching task found, wait for it to appear + if (!matchingTask) { + return; + } - // If task is completed or has processed files, complete the onboarding step - if (!isTaskActive || (matchingTask.processed_files ?? 0) > 0) { - // Set to final step to show "Done" - setCurrentStep(STEP_LIST.length); + // Skip if this task was already handled as a failed task (from a previous failed upload) + // This prevents processing old failed tasks when a new upload starts + if (handledFailedTasksRef.current.has(matchingTask.task_id)) { + // Check if it's a failed task that we've already handled + const hasFailedFile = + matchingTask.files && + Object.values(matchingTask.files).some( + (file) => file.status === "failed" || file.status === "error", + ); + if (hasFailedFile) { + // This is an old failed task that we've already handled, ignore it + console.log( + "Skipping already-handled failed task:", + matchingTask.task_id, + ); + return; + } + // If it's not a failed task, remove it from handled list (it might have succeeded on retry) + handledFailedTasksRef.current.delete(matchingTask.task_id); + } - // Create knowledge filter for uploaded document if requested - // Guard against race condition: only create if not already creating - if (shouldCreateFilter && uploadedFilename && !isCreatingFilter) { - // Reset flags immediately (synchronously) to prevent duplicate creation - setShouldCreateFilter(false); - const filename = uploadedFilename; - setUploadedFilename(null); - setIsCreatingFilter(true); + // Check if any file failed in the matching task + const hasFailedFile = (() => { + // Must have files object + if (!matchingTask.files || typeof matchingTask.files !== "object") { + return false; + } - // Get display name from filename (remove extension for cleaner name) - const displayName = filename.includes(".") - ? filename.substring(0, filename.lastIndexOf(".")) - : filename; + const fileEntries = Object.values(matchingTask.files); - const queryData = JSON.stringify({ - query: "", - filters: { - data_sources: [filename], - document_types: ["*"], - owners: ["*"], - connector_types: ["*"], - }, - limit: 10, - scoreThreshold: 0, - color: "green", - icon: "file", - }); + // Must have at least one file + if (fileEntries.length === 0) { + return false; + } - createFilterMutation - .mutateAsync({ - name: displayName, - description: `Filter for ${filename}`, - queryData: queryData, - }) - .then((result) => { - if (result.filter?.id && typeof window !== "undefined") { - localStorage.setItem( - ONBOARDING_USER_DOC_FILTER_ID_KEY, - result.filter.id, - ); - console.log( - "Created knowledge filter for uploaded document", - result.filter.id, - ); - } - }) - .catch((error) => { - console.error("Failed to create knowledge filter:", error); - }) - .finally(() => { - setIsCreatingFilter(false); - }); - } + // Check if any file has failed status + return fileEntries.some( + (file) => file.status === "failed" || file.status === "error", + ); + })(); - // Refetch nudges to get new ones - refetchNudges(); + // If any file failed, show error and jump back one step (like onboarding-card.tsx) + // Only handle if we haven't already handled this task + if ( + hasFailedFile && + !isCreatingFilter && + !handledFailedTasksRef.current.has(matchingTask.task_id) + ) { + console.error("File failed in task, jumping back one step", matchingTask); - // Wait a bit before completing - setTimeout(() => { - onComplete(); - }, 1000); - } - }, [ - tasks, - currentStep, - onComplete, - refetchNudges, - shouldCreateFilter, - uploadedFilename, - uploadedTaskId, - createFilterMutation, - isCreatingFilter, - ]); + // Mark this task as handled to prevent infinite loops + handledFailedTasksRef.current.add(matchingTask.task_id); - const resetFileInput = () => { - if (fileInputRef.current) { - fileInputRef.current.value = ""; - } - }; + // Extract error messages from failed files + const errorMessages: string[] = []; + if (matchingTask.files) { + Object.values(matchingTask.files).forEach((file) => { + if ( + (file.status === "failed" || file.status === "error") && + file.error + ) { + errorMessages.push(file.error); + } + }); + } - const handleUploadClick = () => { - fileInputRef.current?.click(); - }; + // Also check task-level error + if (matchingTask.error) { + errorMessages.push(matchingTask.error); + } - const performUpload = async (file: File) => { - setIsUploading(true); - try { - setCurrentStep(0); - const result = await uploadFile(file, true, true); // Pass createFilter=true - console.log("Document upload task started successfully"); + // Use the first error message, or a generic message if no errors found + const errorMessage = + errorMessages.length > 0 + ? errorMessages[0] + : "Document failed to ingest. Please try again with a different file."; - // Store task ID to track the specific upload task - if (result.taskId) { - setUploadedTaskId(result.taskId); - } + // Set error message and jump back one step + setError(errorMessage); + setCurrentStep(STEP_LIST.length); - // Store filename and createFilter flag in state to create filter after ingestion succeeds - if (result.createFilter && result.filename) { - setUploadedFilename(result.filename); - setShouldCreateFilter(true); - } + // Clear filter creation flags since ingestion failed + setShouldCreateFilter(false); + setUploadedFilename(null); - // Move to processing step - task monitoring will handle completion - setTimeout(() => { - setCurrentStep(1); - }, 1500); - } catch (error) { - const errorMessage = error instanceof Error ? error.message : "Upload failed"; - console.error("Upload failed", errorMessage); + // Jump back one step after 1 second (go back to upload step) + setTimeout(() => { + setCurrentStep(null); + }, 1000); + return; + } - // Dispatch event that chat context can listen to - // This avoids circular dependency issues - if (typeof window !== "undefined") { - window.dispatchEvent( - new CustomEvent("ingestionFailed", { - detail: { source: "onboarding" }, - }), - ); - } + // Check if the matching task is still active (pending, running, or processing) + const isTaskActive = + matchingTask.status === "pending" || + matchingTask.status === "running" || + matchingTask.status === "processing"; - // Show error toast notification - toast.error("Document upload failed", { - description: errorMessage, - duration: 5000, - }); + // If task is completed successfully (no failures) and has processed files, complete the onboarding step + if ( + (!isTaskActive || (matchingTask.processed_files ?? 0) > 0) && + !hasFailedFile + ) { + // Set to final step to show "Done" + setCurrentStep(STEP_LIST.length); - // Reset on error - setCurrentStep(null); - setUploadedTaskId(null); - } finally { - setIsUploading(false); - } - }; + // Create knowledge filter for uploaded document if requested + // Guard against race condition: only create if not already creating + if (shouldCreateFilter && uploadedFilename && !isCreatingFilter) { + // Reset flags immediately (synchronously) to prevent duplicate creation + setShouldCreateFilter(false); + const filename = uploadedFilename; + setUploadedFilename(null); + setIsCreatingFilter(true); - const handleFileChange = async (event: ChangeEvent) => { - const selectedFile = event.target.files?.[0]; - if (!selectedFile) { - resetFileInput(); - return; - } + // Get display name from filename (remove extension for cleaner name) + const displayName = filename.includes(".") + ? filename.substring(0, filename.lastIndexOf(".")) + : filename; - try { - await performUpload(selectedFile); - } catch (error) { - console.error( - "Unable to prepare file for upload", - (error as Error).message, - ); - } finally { - resetFileInput(); - } - }; + const queryData = JSON.stringify({ + query: "", + filters: { + data_sources: [filename], + document_types: ["*"], + owners: ["*"], + connector_types: ["*"], + }, + limit: 10, + scoreThreshold: 0, + color: "green", + icon: "file", + }); - return ( - - {currentStep === null ? ( - - - - - ) : ( - - - - )} - - ); + // Wait for filter creation to complete before proceeding + createFilterMutation + .mutateAsync({ + name: displayName, + description: `Filter for ${filename}`, + queryData: queryData, + }) + .then((result) => { + if (result.filter?.id && typeof window !== "undefined") { + localStorage.setItem( + ONBOARDING_USER_DOC_FILTER_ID_KEY, + result.filter.id, + ); + console.log( + "Created knowledge filter for uploaded document", + result.filter.id, + ); + } + }) + .catch((error) => { + console.error("Failed to create knowledge filter:", error); + }) + .finally(() => { + setIsCreatingFilter(false); + // Refetch nudges to get new ones + refetchNudges(); + + // Wait a bit before completing (after filter is created) + setTimeout(() => { + onComplete(); + }, 1000); + }); + } else { + // No filter to create, just complete + // Refetch nudges to get new ones + refetchNudges(); + + // Wait a bit before completing + setTimeout(() => { + onComplete(); + }, 1000); + } + } + }, [ + tasks, + currentStep, + onComplete, + refetchNudges, + shouldCreateFilter, + uploadedFilename, + uploadedTaskId, + createFilterMutation, + isCreatingFilter, + ]); + + const resetFileInput = () => { + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + }; + + const handleUploadClick = () => { + // Clear any previous error when user clicks to upload again + setError(null); + fileInputRef.current?.click(); + }; + + const performUpload = async (file: File) => { + setIsUploading(true); + // Clear any previous error when starting a new upload + setError(null); + // Clear handled tasks ref to allow retry + handledFailedTasksRef.current.clear(); + // Reset task ID to prevent matching old failed tasks + setUploadedTaskId(null); + // Clear filter creation flags + setShouldCreateFilter(false); + setUploadedFilename(null); + + try { + setCurrentStep(0); + const result = await uploadFile(file, true, true); // Pass createFilter=true + console.log("Document upload task started successfully"); + + // Store task ID to track the specific upload task + if (result.taskId) { + setUploadedTaskId(result.taskId); + } + + // Store filename and createFilter flag in state to create filter after ingestion succeeds + if (result.createFilter && result.filename) { + setUploadedFilename(result.filename); + setShouldCreateFilter(true); + } + + // Move to processing step - task monitoring will handle completion + setTimeout(() => { + setCurrentStep(1); + }, 1500); + } catch (error) { + const errorMessage = + error instanceof Error ? error.message : "Upload failed"; + console.error("Upload failed", errorMessage); + + // Dispatch event that chat context can listen to + // This avoids circular dependency issues + if (typeof window !== "undefined") { + window.dispatchEvent( + new CustomEvent("ingestionFailed", { + detail: { source: "onboarding" }, + }), + ); + } + + // Show error toast notification + toast.error("Document upload failed", { + description: errorMessage, + duration: 5000, + }); + + // Reset on error + setCurrentStep(null); + setUploadedTaskId(null); + setError(errorMessage); + setShouldCreateFilter(false); + setUploadedFilename(null); + } finally { + setIsUploading(false); + } + }; + + const handleFileChange = async (event: ChangeEvent) => { + const selectedFile = event.target.files?.[0]; + if (!selectedFile) { + resetFileInput(); + return; + } + + try { + await performUpload(selectedFile); + } catch (error) { + console.error( + "Unable to prepare file for upload", + (error as Error).message, + ); + } finally { + resetFileInput(); + } + }; + + return ( + + {currentStep === null ? ( + +
+ + {error && ( + +
+ + + {error} + +
+
+ )} +
+
+ +
+ +
+
+ ) : ( + + + + )} +
+ ); }; export default OnboardingUpload; From 898e1fe7a8ab3ce835aee3f3eec9ff7e326b9b6c Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 5 Dec 2025 17:46:37 -0300 Subject: [PATCH 2/5] removed console log --- frontend/app/chat/page.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/app/chat/page.tsx b/frontend/app/chat/page.tsx index fdeed137..f15cf788 100644 --- a/frontend/app/chat/page.tsx +++ b/frontend/app/chat/page.tsx @@ -73,8 +73,6 @@ function ChatPage() { const lastLoadedConversationRef = useRef(null); const { addTask } = useTask(); - console.log(endpoint, refreshTrigger); - // Check if chat history is loading const { isLoading: isConversationsLoading } = useGetConversationsQuery( endpoint, From 8c9da8fd3a3d37890503962097a3a84b5083c51f Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 5 Dec 2025 17:48:35 -0300 Subject: [PATCH 3/5] remove nudges refetch during onboarding upload --- frontend/app/onboarding/_components/onboarding-upload.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/frontend/app/onboarding/_components/onboarding-upload.tsx b/frontend/app/onboarding/_components/onboarding-upload.tsx index 749f75fd..095f269a 100644 --- a/frontend/app/onboarding/_components/onboarding-upload.tsx +++ b/frontend/app/onboarding/_components/onboarding-upload.tsx @@ -45,8 +45,6 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { refetchInterval: currentStep !== null ? 1000 : false, // Poll every 1 second during upload }); - const { refetch: refetchNudges } = useGetNudgesQuery(null); - // Monitor tasks and call onComplete when file processing is done useEffect(() => { if (currentStep === null || !tasks || !uploadedTaskId) { From 0b40b606c2bf49d5053a24037e56e737df7137f4 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Date: Fri, 5 Dec 2025 17:48:51 -0300 Subject: [PATCH 4/5] fix: chat blocking async requests (#619) * fix chat blocking async requests * fix delete user conversation not being async --- src/agent.py | 20 ++++++------ src/services/chat_service.py | 2 +- .../conversation_persistence_service.py | 31 ++++++++++++------- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/agent.py b/src/agent.py index bd4d257f..dd092643 100644 --- a/src/agent.py +++ b/src/agent.py @@ -47,8 +47,8 @@ def get_conversation_thread(user_id: str, previous_response_id: str = None): return new_conversation -def store_conversation_thread(user_id: str, response_id: str, conversation_state: dict): - """Store conversation both in memory (with function calls) and persist metadata to disk""" +async def store_conversation_thread(user_id: str, response_id: str, conversation_state: dict): + """Store conversation both in memory (with function calls) and persist metadata to disk (async, non-blocking)""" # 1. Store full conversation in memory for function call preservation if user_id not in active_conversations: active_conversations[user_id] = {} @@ -76,7 +76,7 @@ def store_conversation_thread(user_id: str, response_id: str, conversation_state # Don't store actual messages - Langflow has them } - conversation_persistence.store_conversation_thread( + await conversation_persistence.store_conversation_thread( user_id, response_id, metadata_only ) @@ -382,7 +382,7 @@ async def async_chat( # Store the conversation thread with its response_id if response_id: conversation_state["last_activity"] = datetime.now() - store_conversation_thread(user_id, response_id, conversation_state) + await store_conversation_thread(user_id, response_id, conversation_state) logger.debug( "Stored conversation thread", user_id=user_id, response_id=response_id ) @@ -461,7 +461,7 @@ async def async_chat_stream( # Store the conversation thread with its response_id if response_id: conversation_state["last_activity"] = datetime.now() - store_conversation_thread(user_id, response_id, conversation_state) + await store_conversation_thread(user_id, response_id, conversation_state) logger.debug( f"Stored conversation thread for user {user_id} with response_id: {response_id}" ) @@ -549,7 +549,7 @@ async def async_langflow_chat( # Store the conversation thread with its response_id if response_id: conversation_state["last_activity"] = datetime.now() - store_conversation_thread(user_id, response_id, conversation_state) + await store_conversation_thread(user_id, response_id, conversation_state) # Claim session ownership for this user try: @@ -656,7 +656,7 @@ async def async_langflow_chat_stream( # Store the conversation thread with its response_id if response_id: conversation_state["last_activity"] = datetime.now() - store_conversation_thread(user_id, response_id, conversation_state) + await store_conversation_thread(user_id, response_id, conversation_state) # Claim session ownership for this user try: @@ -672,8 +672,8 @@ async def async_langflow_chat_stream( ) -def delete_user_conversation(user_id: str, response_id: str) -> bool: - """Delete a conversation for a user from both memory and persistent storage""" +async def delete_user_conversation(user_id: str, response_id: str) -> bool: + """Delete a conversation for a user from both memory and persistent storage (async, non-blocking)""" deleted = False try: @@ -684,7 +684,7 @@ def delete_user_conversation(user_id: str, response_id: str) -> bool: deleted = True # Delete from persistent storage - conversation_deleted = conversation_persistence.delete_conversation_thread(user_id, response_id) + conversation_deleted = await conversation_persistence.delete_conversation_thread(user_id, response_id) if conversation_deleted: logger.debug(f"Deleted conversation {response_id} from persistent storage for user {user_id}") deleted = True diff --git a/src/services/chat_service.py b/src/services/chat_service.py index e965623c..92c834a8 100644 --- a/src/services/chat_service.py +++ b/src/services/chat_service.py @@ -595,7 +595,7 @@ class ChatService: try: # Delete from local conversation storage from agent import delete_user_conversation - local_deleted = delete_user_conversation(user_id, session_id) + local_deleted = await delete_user_conversation(user_id, session_id) # Delete from Langflow using the monitor API langflow_deleted = await self._delete_langflow_session(session_id) diff --git a/src/services/conversation_persistence_service.py b/src/services/conversation_persistence_service.py index c6b62c24..0c7edc84 100644 --- a/src/services/conversation_persistence_service.py +++ b/src/services/conversation_persistence_service.py @@ -5,6 +5,7 @@ Simple service to persist chat conversations to disk so they survive server rest import json import os +import asyncio from typing import Dict, Any from datetime import datetime import threading @@ -33,8 +34,8 @@ class ConversationPersistenceService: return {} return {} - def _save_conversations(self): - """Save conversations to disk""" + def _save_conversations_sync(self): + """Synchronous save conversations to disk (runs in executor)""" try: with self.lock: with open(self.storage_file, 'w', encoding='utf-8') as f: @@ -43,6 +44,12 @@ class ConversationPersistenceService: except Exception as e: logger.error(f"Error saving conversations to {self.storage_file}: {e}") + async def _save_conversations(self): + """Async save conversations to disk (non-blocking)""" + # Run the synchronous file I/O in a thread pool to avoid blocking the event loop + loop = asyncio.get_event_loop() + await loop.run_in_executor(None, self._save_conversations_sync) + def _count_total_conversations(self, data: Dict[str, Any]) -> int: """Count total conversations across all users""" total = 0 @@ -68,8 +75,8 @@ class ConversationPersistenceService: else: return obj - def store_conversation_thread(self, user_id: str, response_id: str, conversation_state: Dict[str, Any]): - """Store a conversation thread and persist to disk""" + async def store_conversation_thread(self, user_id: str, response_id: str, conversation_state: Dict[str, Any]): + """Store a conversation thread and persist to disk (async, non-blocking)""" if user_id not in self._conversations: self._conversations[user_id] = {} @@ -78,28 +85,28 @@ class ConversationPersistenceService: self._conversations[user_id][response_id] = serialized_conversation - # Save to disk (we could optimize this with batching if needed) - self._save_conversations() + # Save to disk asynchronously (non-blocking) + await self._save_conversations() def get_conversation_thread(self, user_id: str, response_id: str) -> Dict[str, Any]: """Get a specific conversation thread""" user_conversations = self.get_user_conversations(user_id) return user_conversations.get(response_id, {}) - def delete_conversation_thread(self, user_id: str, response_id: str) -> bool: - """Delete a specific conversation thread""" + async def delete_conversation_thread(self, user_id: str, response_id: str) -> bool: + """Delete a specific conversation thread (async, non-blocking)""" if user_id in self._conversations and response_id in self._conversations[user_id]: del self._conversations[user_id][response_id] - self._save_conversations() + await self._save_conversations() logger.debug(f"Deleted conversation {response_id} for user {user_id}") return True return False - def clear_user_conversations(self, user_id: str): - """Clear all conversations for a user""" + async def clear_user_conversations(self, user_id: str): + """Clear all conversations for a user (async, non-blocking)""" if user_id in self._conversations: del self._conversations[user_id] - self._save_conversations() + await self._save_conversations() logger.debug(f"Cleared all conversations for user {user_id}") def get_storage_stats(self) -> Dict[str, Any]: From 0d321890066fdc9c8d0d80b3b4ccc00c1739a08f Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Fri, 5 Dec 2025 17:51:17 -0300 Subject: [PATCH 5/5] remove refetch nudges --- frontend/app/onboarding/_components/onboarding-upload.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/frontend/app/onboarding/_components/onboarding-upload.tsx b/frontend/app/onboarding/_components/onboarding-upload.tsx index 095f269a..a356aa70 100644 --- a/frontend/app/onboarding/_components/onboarding-upload.tsx +++ b/frontend/app/onboarding/_components/onboarding-upload.tsx @@ -217,9 +217,7 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { }) .finally(() => { setIsCreatingFilter(false); - // Refetch nudges to get new ones - refetchNudges(); - + // Wait a bit before completing (after filter is created) setTimeout(() => { onComplete(); @@ -227,8 +225,6 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { }); } else { // No filter to create, just complete - // Refetch nudges to get new ones - refetchNudges(); // Wait a bit before completing setTimeout(() => { @@ -240,7 +236,6 @@ const OnboardingUpload = ({ onComplete }: OnboardingUploadProps) => { tasks, currentStep, onComplete, - refetchNudges, shouldCreateFilter, uploadedFilename, uploadedTaskId,