From 082324b7fc7f0dac2705d6042ac4207ecf40a94b Mon Sep 17 00:00:00 2001 From: leex279 Date: Fri, 12 Sep 2025 19:47:47 +0200 Subject: [PATCH] debug: Add comprehensive logging to trace error handling flow - Add detailed logging to API key validation function - Add debug logs to frontend error parsing - Add debug logs to TanStack Query error handler - This will help identify where error handling is failing in the UI --- .../knowledge/hooks/useKnowledgeQueries.ts | 7 ++ .../services/apiWithEnhancedErrors.ts | 9 +++ python/src/server/api_routes/knowledge_api.py | 66 ++++++++++++------- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/archon-ui-main/src/features/knowledge/hooks/useKnowledgeQueries.ts b/archon-ui-main/src/features/knowledge/hooks/useKnowledgeQueries.ts index 0df5cf4d..4f639fae 100644 --- a/archon-ui-main/src/features/knowledge/hooks/useKnowledgeQueries.ts +++ b/archon-ui-main/src/features/knowledge/hooks/useKnowledgeQueries.ts @@ -260,6 +260,11 @@ export function useCrawlUrl() { return response; }, onError: (error, _variables, context) => { + console.log(`🔍 [Crawl Hook] Received error:`, error); + console.log(`🔍 [Crawl Hook] Error type: ${typeof error}`); + console.log(`🔍 [Crawl Hook] Error keys:`, Object.keys(error || {})); + console.log(`🔍 [Crawl Hook] Is OpenAI error:`, (error as EnhancedError)?.isOpenAIError); + // Rollback optimistic updates on error if (context?.previousKnowledge) { queryClient.setQueryData(knowledgeKeys.lists(), context.previousKnowledge); @@ -278,6 +283,8 @@ export function useCrawlUrl() { const errorMessage = (error as EnhancedError)?.isOpenAIError ? getDisplayErrorMessage(error as EnhancedError) : (error instanceof Error ? error.message : "Failed to start crawl"); + + console.log(`🔍 [Crawl Hook] Final error message for toast:`, errorMessage); showToast(errorMessage, "error"); }, }); diff --git a/archon-ui-main/src/features/knowledge/services/apiWithEnhancedErrors.ts b/archon-ui-main/src/features/knowledge/services/apiWithEnhancedErrors.ts index 0c135515..b61f4898 100644 --- a/archon-ui-main/src/features/knowledge/services/apiWithEnhancedErrors.ts +++ b/archon-ui-main/src/features/knowledge/services/apiWithEnhancedErrors.ts @@ -18,6 +18,10 @@ export async function callKnowledgeAPI( // Use the ETag-aware API client for caching benefits return await callAPIWithETag(endpoint, options); } catch (error: any) { + console.log(`🔍 [Knowledge API] Caught error for ${endpoint}:`, error); + console.log(`🔍 [Knowledge API] Error type: ${typeof error}`); + console.log(`🔍 [Knowledge API] Error keys:`, Object.keys(error || {})); + // Apply enhanced error parsing for OpenAI errors const enhancedError = parseKnowledgeBaseError({ status: error.statusCode || error.status, @@ -25,12 +29,17 @@ export async function callKnowledgeAPI( detail: error.detail }); + console.log(`🔍 [Knowledge API] Enhanced error:`, enhancedError); + console.log(`🔍 [Knowledge API] Is OpenAI error:`, enhancedError.isOpenAIError); + console.log(`🔍 [Knowledge API] Error details:`, enhancedError.errorDetails); + // Preserve the original error structure but enhance with our parsing const finalError = error as EnhancedError; finalError.isOpenAIError = enhancedError.isOpenAIError; finalError.errorDetails = enhancedError.errorDetails; finalError.message = enhancedError.message; + console.log(`🔍 [Knowledge API] Final error to throw:`, finalError); throw finalError; } } diff --git a/python/src/server/api_routes/knowledge_api.py b/python/src/server/api_routes/knowledge_api.py index 62fd576e..dfd696b8 100644 --- a/python/src/server/api_routes/knowledge_api.py +++ b/python/src/server/api_routes/knowledge_api.py @@ -100,21 +100,24 @@ async def _validate_openai_api_key() -> None: Raises: HTTPException: 401 if API key is invalid/missing, 429 if quota exhausted """ + # Import embedding exceptions for specific error handling + from ..services.embeddings.embedding_exceptions import ( + EmbeddingAuthenticationError, + EmbeddingQuotaExhaustedError, + ) + try: # Test the API key with a minimal embedding request from ..services.embeddings.embedding_service import create_embedding + logger.info("🔑 Validating OpenAI API key before starting operation...") # Try to create a test embedding with minimal content - await create_embedding(text="test") - - except Exception as e: - # Import embedding exceptions for specific error handling - from ..services.embeddings.embedding_exceptions import ( - EmbeddingAuthenticationError, - EmbeddingQuotaExhaustedError, - ) - - if isinstance(e, EmbeddingAuthenticationError): + test_result = await create_embedding(text="test") + + if test_result: + logger.info("✅ OpenAI API key validation successful") + else: + logger.error("❌ OpenAI API key validation failed - no embedding returned") raise HTTPException( status_code=401, detail={ @@ -123,20 +126,35 @@ async def _validate_openai_api_key() -> None: "error_type": "authentication_failed" } ) - elif isinstance(e, EmbeddingQuotaExhaustedError): - raise HTTPException( - status_code=429, - detail={ - "error": "OpenAI quota exhausted", - "message": "Your OpenAI API key has no remaining credits. Please add credits to your account.", - "error_type": "quota_exhausted" - } - ) - else: - # For any other errors, allow the operation to continue - # The error will be caught later during actual processing - logger.warning(f"API key validation failed with unexpected error: {e}") - pass + + except EmbeddingAuthenticationError as e: + logger.error(f"❌ OpenAI authentication failed: {e}") + raise HTTPException( + status_code=401, + detail={ + "error": "Invalid OpenAI API key", + "message": "Please verify your OpenAI API key in Settings before starting a crawl.", + "error_type": "authentication_failed", + "api_key_prefix": getattr(e, "api_key_prefix", None), + } + ) from None + except EmbeddingQuotaExhaustedError as e: + logger.error(f"❌ OpenAI quota exhausted: {e}") + raise HTTPException( + status_code=429, + detail={ + "error": "OpenAI quota exhausted", + "message": "Your OpenAI API key has no remaining credits. Please add credits to your account.", + "error_type": "quota_exhausted", + "tokens_used": getattr(e, "tokens_used", None), + } + ) from None + except Exception as e: + # For any other errors, log them but allow the operation to continue + # The error will be caught later during actual processing + logger.warning(f"⚠️ API key validation failed with unexpected error: {e}") + # Don't block the operation for unexpected validation errors + pass # Request Models