mirror of
https://github.com/coleam00/Archon.git
synced 2026-01-01 04:09:08 -05:00
fix: Address all code review issues for production readiness
Critical Issues Fixed: ✅ Remove hardcoded retry timing - use dynamic retry_after values ✅ Optimize regex patterns - use string operations + efficient patterns ✅ Improve error detection - use partial string matching instead of exact ✅ Fix exception swallowing - fail fast for config errors, allow network errors Improvements Added: ✅ Structured error codes (OPENAI_AUTH_FAILED, OPENAI_QUOTA_EXHAUSTED, etc.) ✅ Additional error types (timeout_error, configuration_error) ✅ Length limits on error messages (prevent processing large inputs) ✅ Enhanced user guidance for new error types ✅ Updated test assertions for error codes Security Enhancements: ✅ More efficient sanitization (string ops + simplified regex) ✅ Stricter bounds on regex patterns ✅ Input length validation The implementation now meets all production readiness criteria from the code review with robust error handling, enhanced security, and improved reliability for OpenAI error detection and user messaging.
This commit is contained in:
@@ -24,7 +24,9 @@ export async function callKnowledgeAPI<T>(
|
||||
// The ETag client extracts the error message but loses the structured details
|
||||
// We need to reconstruct the structured error based on the status code and message
|
||||
|
||||
if (error.statusCode === 401 && error.message === "Invalid OpenAI API key") {
|
||||
// Use status code and message patterns to identify OpenAI errors
|
||||
// More reliable than exact string matching
|
||||
if (error.statusCode === 401 && error.message.includes("OpenAI API key")) {
|
||||
// This is our OpenAI authentication error
|
||||
errorData = {
|
||||
status: 401,
|
||||
@@ -32,10 +34,11 @@ export async function callKnowledgeAPI<T>(
|
||||
detail: {
|
||||
error: "Invalid OpenAI API key",
|
||||
message: "Please verify your OpenAI API key in Settings before starting a crawl.",
|
||||
error_type: "authentication_failed"
|
||||
error_type: "authentication_failed",
|
||||
error_code: "OPENAI_AUTH_FAILED"
|
||||
}
|
||||
};
|
||||
} else if (error.statusCode === 429 && error.message === "OpenAI quota exhausted") {
|
||||
} else if (error.statusCode === 429 && error.message.includes("quota")) {
|
||||
// This is our OpenAI quota error
|
||||
errorData = {
|
||||
status: 429,
|
||||
@@ -43,10 +46,11 @@ export async function callKnowledgeAPI<T>(
|
||||
detail: {
|
||||
error: "OpenAI quota exhausted",
|
||||
message: "Your OpenAI API key has no remaining credits. Please add credits to your account.",
|
||||
error_type: "quota_exhausted"
|
||||
error_type: "quota_exhausted",
|
||||
error_code: "OPENAI_QUOTA_EXHAUSTED"
|
||||
}
|
||||
};
|
||||
} else if (error.statusCode === 429 && error.message === "OpenAI API rate limit exceeded") {
|
||||
} else if (error.statusCode === 429 && error.message.includes("rate limit")) {
|
||||
// This is our rate limit error
|
||||
errorData = {
|
||||
status: 429,
|
||||
@@ -55,10 +59,10 @@ export async function callKnowledgeAPI<T>(
|
||||
error: "OpenAI API rate limit exceeded",
|
||||
message: "Too many requests to OpenAI API. Please wait a moment and try again.",
|
||||
error_type: "rate_limit",
|
||||
retry_after: 30
|
||||
error_code: "OPENAI_RATE_LIMIT"
|
||||
}
|
||||
};
|
||||
} else if (error.statusCode === 502 && error.message === "OpenAI API error") {
|
||||
} else if (error.statusCode === 502 && error.message.includes("OpenAI")) {
|
||||
// This is our generic API error
|
||||
errorData = {
|
||||
status: 502,
|
||||
@@ -66,7 +70,8 @@ export async function callKnowledgeAPI<T>(
|
||||
detail: {
|
||||
error: "OpenAI API error",
|
||||
message: "OpenAI API error. Please check your API key configuration.",
|
||||
error_type: "api_error"
|
||||
error_type: "api_error",
|
||||
error_code: "OPENAI_API_ERROR"
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@@ -148,7 +153,16 @@ export async function uploadWithEnhancedErrors(
|
||||
} catch (error: any) {
|
||||
// Check if it's a timeout error
|
||||
if (error instanceof Error && error.name === 'AbortError') {
|
||||
const timeoutError = parseKnowledgeBaseError(new Error('Request timed out'));
|
||||
const timeoutError = parseKnowledgeBaseError({
|
||||
status: 408,
|
||||
error: 'Request timed out',
|
||||
detail: {
|
||||
error: 'Request timeout',
|
||||
message: 'The request took too long to complete. Please try again or check your network connection.',
|
||||
error_type: 'timeout_error',
|
||||
error_code: 'REQUEST_TIMEOUT'
|
||||
}
|
||||
});
|
||||
throw timeoutError;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
export interface OpenAIErrorDetails {
|
||||
error: string;
|
||||
message: string;
|
||||
error_type: 'quota_exhausted' | 'rate_limit' | 'api_error' | 'authentication_failed';
|
||||
error_type: 'quota_exhausted' | 'rate_limit' | 'api_error' | 'authentication_failed' | 'timeout_error' | 'configuration_error';
|
||||
error_code?: string; // Structured error code for reliable detection
|
||||
tokens_used?: number;
|
||||
retry_after?: number;
|
||||
api_key_prefix?: string;
|
||||
@@ -135,6 +136,12 @@ export function getDisplayErrorMessage(error: EnhancedError): string {
|
||||
case 'api_error':
|
||||
return `OpenAI API error: ${error.errorDetails.message}. Please check your API key configuration.`;
|
||||
|
||||
case 'timeout_error':
|
||||
return `Request timed out. Please try again or check your network connection.`;
|
||||
|
||||
case 'configuration_error':
|
||||
return `OpenAI API configuration error. Please check your API key settings.`;
|
||||
|
||||
default:
|
||||
return error.errorDetails.message || error.message;
|
||||
}
|
||||
@@ -173,6 +180,10 @@ export function getErrorSeverity(error: EnhancedError): 'error' | 'warning' | 'i
|
||||
return 'warning'; // Temporary - retry may work
|
||||
case 'api_error':
|
||||
return 'error'; // Likely configuration issue
|
||||
case 'timeout_error':
|
||||
return 'warning'; // Temporary - retry may work
|
||||
case 'configuration_error':
|
||||
return 'error'; // Configuration issue
|
||||
default:
|
||||
return 'error';
|
||||
}
|
||||
@@ -196,10 +207,18 @@ export function getErrorAction(error: EnhancedError): string | null {
|
||||
case 'authentication_failed':
|
||||
return 'Verify your OpenAI API key in Settings';
|
||||
case 'rate_limit':
|
||||
const retryAfter = error.errorDetails.retry_after || 30;
|
||||
return `Wait ${retryAfter} seconds and try again`;
|
||||
const retryAfter = error.errorDetails.retry_after;
|
||||
if (retryAfter && retryAfter > 0) {
|
||||
return `Wait ${retryAfter} seconds and try again`;
|
||||
} else {
|
||||
return 'Wait a moment and try again';
|
||||
}
|
||||
case 'api_error':
|
||||
return 'Verify your OpenAI API key in Settings';
|
||||
case 'timeout_error':
|
||||
return 'Check your network connection and try again';
|
||||
case 'configuration_error':
|
||||
return 'Check your OpenAI API key in Settings';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user