ZhuLinsen/daily_stock_analysis · error · AlertNotFoundError
not_found
not_found
Error message
Alert rule not found: {rule_id} What it means
AlertNotFoundError (subclass of AlertServiceError, itself a ValueError) raised in AlertService.get_rule (src/services/alert_service.py:117) when AlertRepository.get_rule returns no row for the given rule_id — i.e. no alert rule with that primary key exists (or it was deleted). It carries code 'not_found' semantics for the API layer to map to HTTP 404.
Source
Thrown at src/services/alert_service.py:117
error_code = "unsupported_alert_type"
class AlertService:
"""Business logic for alert rule CRUD and dry-run evaluation."""
def __init__(self, db_manager: Optional[DatabaseManager] = None):
self.db = db_manager or DatabaseManager.get_instance()
self.repo = AlertRepository(self.db)
def create_rule(self, payload: Dict[str, Any]) -> Dict[str, Any]:
fields = self._normalize_rule_payload(payload)
return self._serialize_rule(self.repo.create_rule(fields))
def get_rule(self, rule_id: int) -> Dict[str, Any]:
row = self.repo.get_rule(rule_id)
if row is None:
raise AlertNotFoundError(f"Alert rule not found: {rule_id}")
return self._serialize_rule(row)
def update_rule(self, rule_id: int, payload: Dict[str, Any]) -> Dict[str, Any]:
row = self.repo.get_rule(rule_id)
if row is None:
raise AlertNotFoundError(f"Alert rule not found: {rule_id}")
if not payload:
raise AlertServiceError("No fields provided for update")
self._validate_rule_update_payload(payload)
merged = self._serialize_rule_base(row)
merged.update(payload)
fields = self._normalize_rule_payload(merged, source=merged.get("source") or "api")
updated = self.repo.update_rule(rule_id, fields)
if updated is None:
raise AlertNotFoundError(f"Alert rule not found: {rule_id}")
return self._serialize_rule(updated)
View on GitHub (pinned to 5159bd72e8)
Solutions
- List rules (list_rules / GET collection) to see current ids and re-fetch the correct one.
- Handle 404/AlertNotFoundError in the client by refreshing the rule list and dropping the stale entry.
- Verify you are pointed at the right environment/database for the id you hold.
Example fix
# before
rule = service.get_rule(123) # KeyError-style crash if deleted
# after
try:
rule = service.get_rule(123)
except AlertNotFoundError:
rules = service.list_rules(page=1, page_size=50)
rule = next((r for r in rules['items'] if ...), None) Defensive patterns
Strategy: try-catch
Validate before calling
rules = service.list_rules(page=1, page_size=200)
known_ids = {r['id'] for r in rules['items']}
if rule_id not in known_ids:
return not_found(f'rule {rule_id} not in current list') Try / catch
from src.services.alert_service import AlertNotFoundError
try:
rule = service.get_rule(rule_id)
except AlertNotFoundError:
return JSONResponse(status_code=404, content={'detail': f'alert rule {rule_id} not found'}) Prevention
- Map AlertNotFoundError to HTTP 404 at the API layer once, centrally.
- Refresh rule lists after deletes instead of caching ids indefinitely.
- Pass ids only from a list response of the same environment.
When it happens
Trigger: GET /api/alerts/rules/{rule_id} with an id that never existed or was deleted; a stale rule_id held in the frontend after another tab/session removed it; an id from a different database/environment (dev id used against prod).
Common situations: Cached UI lists referencing deleted rules; database reset/reseed while clients keep old ids; typos in manual curl/scripts; concurrent delete-then-read races.
Related errors
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/77f02330d7fa4d62.
Report an issue: GitHub.