7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
5.8 KiB
5.8 KiB
News API Exception Handling
Overview
The news API module now uses a structured exception handling approach instead of returning error dictionaries. This provides better error handling, cleaner code, and consistent API responses.
Exception Hierarchy
All news API exceptions inherit from NewsAPIException, which provides:
- Human-readable error messages
- HTTP status codes
- Machine-readable error codes
- Optional additional details
from local_deep_research.news.exceptions import NewsAPIException
class NewsAPIException(Exception):
def __init__(self, message: str, status_code: int = 500,
error_code: Optional[str] = None,
details: Optional[Dict[str, Any]] = None)
Available Exceptions
InvalidLimitException
- Status Code: 400
- Error Code:
INVALID_LIMIT - Usage: When an invalid limit parameter is provided
- Example:
if limit < 1:
raise InvalidLimitException(limit)
SubscriptionNotFoundException
- Status Code: 404
- Error Code:
SUBSCRIPTION_NOT_FOUND - Usage: When a requested subscription doesn't exist
- Example:
if not subscription:
raise SubscriptionNotFoundException(subscription_id)
SubscriptionCreationException
- Status Code: 500
- Error Code:
SUBSCRIPTION_CREATE_FAILED - Usage: When subscription creation fails
- Example:
except Exception as e:
raise SubscriptionCreationException(str(e), {"query": query})
SubscriptionUpdateException
- Status Code: 500
- Error Code:
SUBSCRIPTION_UPDATE_FAILED - Usage: When subscription update fails
SubscriptionDeletionException
- Status Code: 500
- Error Code:
SUBSCRIPTION_DELETE_FAILED - Usage: When subscription deletion fails
DatabaseAccessException
- Status Code: 500
- Error Code:
DATABASE_ERROR - Usage: When database operations fail
- Example:
except Exception as e:
raise DatabaseAccessException("operation_name", str(e))
NewsFeedGenerationException
- Status Code: 500
- Error Code:
FEED_GENERATION_FAILED - Usage: When news feed generation fails
ResearchProcessingException
- Status Code: 500
- Error Code:
RESEARCH_PROCESSING_FAILED - Usage: When processing research items fails
NotImplementedException
- Status Code: 501
- Error Code:
NOT_IMPLEMENTED - Usage: For features not yet implemented
- Example:
raise NotImplementedException("feature_name")
InvalidParameterException
- Status Code: 400
- Error Code:
INVALID_PARAMETER - Usage: When invalid parameters are provided
SchedulerNotificationException
- Status Code: 500
- Error Code:
SCHEDULER_NOTIFICATION_FAILED - Usage: When scheduler notification fails (non-critical)
Flask Integration
Error Handlers
The Flask application automatically handles NewsAPIException and its subclasses:
@app.errorhandler(NewsAPIException)
def handle_news_api_exception(error):
return jsonify(error.to_dict()), error.status_code
Response Format
All exceptions are converted to consistent JSON responses:
{
"error": "Human-readable error message",
"error_code": "MACHINE_READABLE_CODE",
"status_code": 400,
"details": {
"additional": "context",
"if": "available"
}
}
Migration Guide
Before (Error Dictionaries)
def get_news_feed(limit):
if limit < 1:
return {
"error": "Limit must be at least 1",
"news_items": []
}
try:
# ... code ...
except Exception as e:
logger.exception("Error getting news feed")
return {"error": str(e), "news_items": []}
After (Exceptions)
def get_news_feed(limit):
if limit < 1:
raise InvalidLimitException(limit)
try:
# ... code ...
except NewsAPIException:
raise # Re-raise our custom exceptions
except Exception as e:
logger.exception("Error getting news feed")
raise NewsFeedGenerationException(str(e))
Benefits
- Cleaner Code: Functions focus on their primary logic without error response formatting
- Consistent Error Handling: All errors follow the same format
- Better Testing: Easier to test exception cases with pytest.raises
- Type Safety: IDEs can better understand return types
- Centralized Logging: Error logging can be handled in one place
- HTTP Status Codes: Proper HTTP status codes are automatically set
Testing
Test exception handling using pytest:
import pytest
from local_deep_research.news.exceptions import InvalidLimitException
def test_invalid_limit():
with pytest.raises(InvalidLimitException) as exc_info:
news_api.get_news_feed(limit=-1)
assert exc_info.value.status_code == 400
assert exc_info.value.details["provided_limit"] == -1
Best Practices
- Always catch and re-raise NewsAPIException subclasses:
except NewsAPIException:
raise # Let Flask handle it
except Exception as e:
# Convert to appropriate NewsAPIException
raise DatabaseAccessException("operation", str(e))
- Include relevant details:
raise SubscriptionCreationException(
"Database constraint violated",
details={"query": query, "type": subscription_type}
)
-
Use appropriate exception types: Choose the most specific exception that matches the error condition
-
Log before raising: For unexpected errors, log the full exception before converting to NewsAPIException
Future Improvements
- Add retry logic for transient errors
- Implement exception metrics/monitoring
- Add internationalization support for error messages
- Create exception middleware for advanced error handling