Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 5,558 Bytes
61d29fc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """
Structured error models for API responses.
Provides user-friendly error messages with expandable technical details.
"""
from pydantic import BaseModel, Field
from typing import Optional, Dict, Any
class ErrorDetail(BaseModel):
"""Structured error detail with user-friendly message and technical info."""
message: str = Field(
...,
description="User-friendly error message"
)
error_type: str = Field(
...,
description="Type of error (e.g., 'data_not_found', 'network_error', 'validation_error')"
)
technical_details: Optional[str] = Field(
None,
description="Technical error details for debugging (expandable in UI)"
)
suggestions: Optional[list[str]] = Field(
None,
description="Helpful suggestions for the user"
)
metadata: Optional[Dict[str, Any]] = Field(
None,
description="Additional context (state, dataset name, etc.)"
)
def parse_error(exception: Exception, context: Optional[Dict[str, Any]] = None) -> ErrorDetail:
"""
Parse an exception into a structured ErrorDetail with user-friendly message.
Args:
exception: The exception to parse
context: Additional context (state, dataset, etc.)
Returns:
ErrorDetail with user-friendly message and technical details
"""
error_str = str(exception)
context = context or {}
# Parse HuggingFace dataset not found errors
if "HTTP 404 Not Found" in error_str and "huggingface.co/datasets" in error_str:
# Extract dataset name from URL
import re
match = re.search(r'datasets/([^/]+/[^/]+)/', error_str)
dataset_name = match.group(1) if match else "unknown"
# Extract state from dataset name or context
state = context.get('state', 'Unknown')
data_type = 'bills' if 'bills' in dataset_name else 'data'
return ErrorDetail(
message=f"No {data_type} data available for {state.upper()}",
error_type="data_not_found",
technical_details=f"Dataset '{dataset_name}' not found on HuggingFace.\n\nFull error: {error_str}",
suggestions=[
f"Try a different state - we have data for 50+ states",
f"Check /api/bills/map to see which states have {data_type} data",
"Contact support if you believe this data should be available"
],
metadata={
"dataset": dataset_name,
"state": state,
"data_type": data_type
}
)
# Parse file not found errors (local environment)
elif "No such file or directory" in error_str or "FileNotFoundError" in error_str:
state = context.get('state', 'Unknown')
data_type = context.get('data_type', 'data')
return ErrorDetail(
message=f"No {data_type} available for {state.upper()}",
error_type="data_not_found",
technical_details=error_str,
suggestions=[
f"This state may not have {data_type} in our database yet",
"Try a different state or check which states have data",
"Data is being continuously added - check back later"
],
metadata={
"state": state,
"data_type": data_type
}
)
# Parse DuckDB/SQL errors
elif "DuckDB" in error_str or "SYNTAX ERROR" in error_str or "LINE" in error_str:
return ErrorDetail(
message="Database query error - please check your search parameters",
error_type="query_error",
technical_details=error_str,
suggestions=[
"Try simplifying your search query",
"Check that all parameters are valid",
"Contact support if the issue persists"
],
metadata=context
)
# Parse network/timeout errors
elif "timeout" in error_str.lower() or "connection" in error_str.lower():
return ErrorDetail(
message="Network request timed out - please try again",
error_type="network_error",
technical_details=error_str,
suggestions=[
"Try again in a few seconds",
"Check your internet connection",
"The server may be temporarily busy"
],
metadata=context
)
# Parse validation errors
elif "validation" in error_str.lower() or "invalid" in error_str.lower():
return ErrorDetail(
message="Invalid request parameters",
error_type="validation_error",
technical_details=error_str,
suggestions=[
"Check that all required parameters are provided",
"Verify parameter formats (e.g., state codes should be 2 letters)",
"See API documentation for valid parameter values"
],
metadata=context
)
# Generic error fallback
else:
return ErrorDetail(
message="An unexpected error occurred",
error_type="server_error",
technical_details=error_str,
suggestions=[
"Try again in a few moments",
"Contact support if the issue persists",
"Check the technical details for more information"
],
metadata=context
)
|