Skip to content
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
96c2875
Fix OpenAI quota exhaustion error handling in RAG queries
leex279 Aug 19, 2025
2c16ed9
Remove unused variable to fix linting
leex279 Aug 19, 2025
f23faea
Add comprehensive frontend error handling for OpenAI API errors
leex279 Aug 19, 2025
c3a9548
Fix #362: Enhance OpenAI API error handling with sanitization and ret…
leex279 Aug 20, 2025
6652873
Implement code review findings: Security and performance improvements
leex279 Aug 20, 2025
3c0fc55
Fix OpenAI API key cache invalidation regression
leex279 Aug 21, 2025
5fbe8fb
Merge latest main into bugfix-issue-362 - Keep OpenAI error handling …
leex279 Aug 21, 2025
0a8bea6
Add comprehensive OpenAI AuthenticationError handling
leex279 Aug 21, 2025
f770675
Fix crawl success reporting when embeddings fail
leex279 Aug 21, 2025
c3cf1ee
RAG: surface OpenAI auth errors as 401; fix single-vector embedding c…
Aug 29, 2025
2c3b8ef
PR #521: address CodeRabbit review β€” consistent 401 payload; mask key…
Aug 29, 2025
46a98da
Merge PR 521: Fix authentication error handling in RAG
leex279 Aug 30, 2025
0fce8a5
Add upfront OpenAI API key validation to prevent wasted crawling
leex279 Aug 30, 2025
3337b90
Fix UI error display: restore enhanced error handling in KnowledgeBas…
leex279 Aug 30, 2025
de8aa8a
fix: Address CodeRabbit review comments
leex279 Aug 31, 2025
2ffe1ac
Merge latest main changes into OpenAI error handling branch
leex279 Aug 31, 2025
26d0588
fix: Improve UI error display for OpenAI authentication errors
leex279 Aug 31, 2025
afe8c56
fix: Add clear 401 status code to authentication error message
leex279 Aug 31, 2025
39451b7
debug: Add detailed logging to diagnose error parsing issue
leex279 Aug 31, 2025
071840a
fix: Use enhanced UI error messages directly in error parsing
leex279 Aug 31, 2025
71e83dd
fix: Address CodeRabbit review suggestions for error handling
leex279 Aug 31, 2025
3e09eba
fix: Resolve backend test failures
leex279 Aug 31, 2025
99375c6
fix: Update tests for fail-fast behavior and fix storage mocks
leex279 Aug 31, 2025
1f382e5
fix: Add comprehensive mocking to prevent real API calls in tests
leex279 Aug 31, 2025
7c8d3e4
fix: Correct chunk count in document storage test
leex279 Aug 31, 2025
5ef7c2f
fix: Remove non-existent EmbeddingResult import causing test collecti…
leex279 Aug 31, 2025
e1aec98
fix: Update tests to expect masked API key prefix
leex279 Aug 31, 2025
65c4363
fix: Allow test-specific mocking by removing autouse create_embedding…
leex279 Aug 31, 2025
9cc7023
fix: Mock search_documents directly to test error handling pipeline
leex279 Aug 31, 2025
efeaaab
Delete OPENAI_ERROR_HANDLING.md
leex279 Aug 31, 2025
7a3775a
fix: Address critical and warning issues from code review
leex279 Aug 31, 2025
ff16882
Merge origin/main into bugfix-issue-362
leex279 Sep 6, 2025
e5235e6
Fix missing import for enhanced error handling in KnowledgeBasePage
leex279 Sep 6, 2025
57ee971
Add debug logging to frontend error parsing
leex279 Sep 6, 2025
5562605
Merge remote-tracking branch 'origin/main' into bugfix-issue-362
leex279 Sep 6, 2025
63c51e3
fix: Address ReDoS vulnerability in regex patterns
leex279 Sep 6, 2025
80e0cff
fix: Optimize isSafeObject performance in error handler
leex279 Sep 6, 2025
faf5ece
fix: Add frontend sanitization for sensitive data in error messages
leex279 Sep 6, 2025
9c85295
fix: Sanitize string error messages to prevent sensitive data leakage
leex279 Sep 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions OPENAI_ERROR_HANDLING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# OpenAI Error Handling Enhancement

**Related to GitHub Issue #362**

## Problem
Users experienced silent failures when OpenAI API quota was exhausted, receiving empty RAG query results without any error indication.

## Solution
Enhanced error handling throughout the stack to catch, preserve, and display specific OpenAI API errors with actionable user guidance.

## Changes Made

### Backend (Python)

#### 1. Fixed Error Propagation in RAG Service
**File**: `python/src/server/services/search/rag_service.py`

- Enhanced `search_documents()` method to re-raise specific embedding errors instead of returning empty lists
- Added imports for `EmbeddingQuotaExhaustedError`, `EmbeddingRateLimitError`, `EmbeddingAPIError`

```python
except (EmbeddingQuotaExhaustedError, EmbeddingRateLimitError, EmbeddingAPIError):
# Re-raise embedding errors so they propagate to the API layer with specific error info
raise
```

#### 2. Enhanced API Error Handling
**File**: `python/src/server/api_routes/knowledge_api.py`

- Added specific error handling for OpenAI errors in `perform_rag_query()` endpoint
- Returns HTTP 429 with detailed error information for quota/rate limit errors
- Returns HTTP 502 with specific messages for API errors

```python
if isinstance(e, EmbeddingQuotaExhaustedError):
raise HTTPException(
status_code=429,
detail={
"error": "OpenAI API quota exhausted",
"message": "Your OpenAI API key has no remaining credits...",
"error_type": "quota_exhausted",
"tokens_used": getattr(e, "tokens_used", None),
}
)
```

#### 3. Comprehensive Test Coverage
**File**: `python/tests/test_openai_quota_error_handling.py`

- Tests error propagation from embedding service through RAG service to API endpoint
- Verifies correct HTTP status codes and error details
- Ensures successful queries still work after changes

### Frontend (TypeScript/React)

#### 1. Error Parsing and Enhancement
**File**: `archon-ui-main/src/services/knowledgeBaseErrorHandler.ts`

- Parses API errors to identify OpenAI-specific issues
- Provides user-friendly error messages and suggested actions
- Categorizes errors by severity level

#### 2. Enhanced Knowledge Base Service
**File**: `archon-ui-main/src/services/knowledgeBaseService.ts`

- Integrated error handler into API request pipeline
- Preserves OpenAI error details through the service layer

#### 3. React Components for Error Display
**Files**:
- `archon-ui-main/src/components/ui/ErrorAlert.tsx`
- `archon-ui-main/src/components/ui/Alert.tsx`

- Provides specialized UI components for displaying OpenAI errors
- Shows actionable guidance (e.g., "Check your OpenAI billing dashboard")
- Includes error severity indicators and suggested actions

## Usage Examples

### Backend API Response (Before)
```json
{
"detail": {"error": "RAG query failed: Unknown error"}
}
```

### Backend API Response (After)
```json
{
"detail": {
"error": "OpenAI API quota exhausted",
"message": "Your OpenAI API key has no remaining credits. Please add credits to your OpenAI account or check your billing settings.",
"error_type": "quota_exhausted",
"tokens_used": 1000
}
}
```

### Frontend Usage
```tsx
import { useErrorHandler, ErrorAlert } from '../components/ui/ErrorAlert';
import { knowledgeBaseService } from '../services/knowledgeBaseService';

function SearchComponent() {
const { error, setError, clearError } = useErrorHandler();

const handleSearch = async (query: string) => {
try {
clearError();
const results = await knowledgeBaseService.searchKnowledgeBase(query);
// Handle successful results...
} catch (err) {
setError(err as EnhancedError);
}
};

return (
<>
<ErrorAlert error={error} onDismiss={clearError} />
{/* Search UI components */}
</>
);
}
```

## Error Types Handled

1. **Quota Exhausted** (HTTP 429)
- Message: "Your OpenAI API key has no remaining credits..."
- Action: "Check your OpenAI billing dashboard and add credits"

2. **Rate Limited** (HTTP 429)
- Message: "Too many requests to OpenAI API..."
- Action: "Wait 30 seconds and try again"

3. **API Error** (HTTP 502)
- Message: "OpenAI API error: [specific error]"
- Action: "Verify your OpenAI API key in Settings"

## Testing

Run the comprehensive test suite:
```bash
cd python
uv run pytest tests/test_openai_quota_error_handling.py -v
```

## Benefits

1. **Clear Error Messages**: Users now see specific, actionable error messages instead of silent failures
2. **Better Debugging**: Developers get detailed error context in logs
3. **Improved UX**: Users understand what went wrong and how to fix it
4. **Reduced Support Load**: Self-service error resolution with guided actions

This enhancement resolves GitHub issue #362 and significantly improves the user experience when OpenAI API issues occur.
30 changes: 30 additions & 0 deletions archon-ui-main/src/components/mcp/ToolTestingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { X, Play, ChevronDown, TerminalSquare, Copy, Check, MinusCircle, Maximiz
import { Client, Tool } from './MCPClients';
import { Button } from '../ui/Button';
import { mcpClientService } from '../../services/mcpClientService';
import { ErrorAlert, useErrorHandler } from '../ui/ErrorAlert';
import { parseKnowledgeBaseError, EnhancedError } from '../../services/knowledgeBaseErrorHandler';

interface ToolTestingPanelProps {
client: Client | null;
Expand Down Expand Up @@ -37,6 +39,7 @@ export const ToolTestingPanel = ({
const [isResizing, setIsResizing] = useState(false);
const [isMaximized, setIsMaximized] = useState(false);
const [isExecuting, setIsExecuting] = useState(false);
const { error, setError, clearError } = useErrorHandler();
const terminalRef = useRef<HTMLDivElement>(null);
const resizeHandleRef = useRef<HTMLDivElement>(null);
const panelRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -92,6 +95,13 @@ export const ToolTestingPanel = ({
};
}, [isResizing]);

// Cleanup error state on component unmount
useEffect(() => {
return () => {
clearError(); // Clear any pending errors when component unmounts
};
}, [clearError]);

// Handle tool selection
const handleToolSelect = (tool: Tool) => {
setSelectedTool(tool);
Expand Down Expand Up @@ -260,9 +270,23 @@ export const ToolTestingPanel = ({

} catch (error: any) {
console.error('MCP tool execution failed:', error);

// Parse error through enhanced error handler for better user experience
const enhancedError = parseKnowledgeBaseError(error);
setError(enhancedError);

setTimeout(() => {
addTypingLine(`> ERROR: Failed to execute tool on ${client.name}`, false, true);
addTypingLine(`> ${error.message || 'Unknown error occurred'}`, false, true);

// Add special handling for OpenAI/RAG related errors
if (enhancedError.isOpenAIError && enhancedError.errorDetails) {
addTypingLine(`> Error Type: ${enhancedError.errorDetails.error_type}`, false, true);
if (enhancedError.errorDetails.tokens_used) {
addTypingLine(`> Tokens Used: ${enhancedError.errorDetails.tokens_used}`, false, true);
}
}

addTypingLine('> Execution failed');
setIsExecuting(false);
}, 300);
Expand All @@ -286,6 +310,9 @@ export const ToolTestingPanel = ({
const executeSelectedTool = () => {
if (!selectedTool || !client || isExecuting) return;

// Clear any previous errors
clearError();

// Validate required parameters
const validationError = validateParameters();
if (validationError) {
Expand Down Expand Up @@ -415,6 +442,9 @@ export const ToolTestingPanel = ({

{/* Content */}
<div className="px-6 py-4 h-[calc(100%-73px)] overflow-y-auto">
{/* Error Alert for OpenAI/RAG errors */}
<ErrorAlert error={error} onDismiss={clearError} />

{client.tools.length === 0 ? (
<div className="flex items-center justify-center h-full">
<div className="text-center">
Expand Down
46 changes: 46 additions & 0 deletions archon-ui-main/src/components/ui/Alert.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Basic Alert component for error display
*
* Provides consistent styling for alerts throughout the application.
*/

import React from 'react';

interface AlertProps {
children: React.ReactNode;
variant?: 'default' | 'destructive';
className?: string;
}

export const Alert: React.FC<AlertProps> = ({
children,
variant = 'default',
className = ''
}) => {
const baseClasses = 'p-4 border rounded-lg';
const variantClasses = variant === 'destructive'
? 'border-red-300 bg-red-50 text-red-800'
: 'border-blue-300 bg-blue-50 text-blue-800';

return (
<div className={`${baseClasses} ${variantClasses} ${className}`}>
{children}
</div>
);
};

interface AlertDescriptionProps {
children: React.ReactNode;
className?: string;
}

export const AlertDescription: React.FC<AlertDescriptionProps> = ({
children,
className = ''
}) => {
return (
<div className={className}>
{children}
</div>
);
};
Loading