ZhuLinsen/daily_stock_analysis · error · DecisionSignalNotFoundError
not_found
not_found
Error message
Decision signal not found: {signal_id_norm} What it means
When evaluating decision-signal outcomes, if a specific signal_id was requested but repo.list_candidate_signals returns no rows, the service raises DecisionSignalNotFoundError (a ValueError subclass, code=not_found). The API layer maps it to an HTTP 404-style error on the outcome endpoints.
Source
Thrown at src/services/decision_signal_outcome_service.py:143
market=market_norm,
action=action_norm,
source_type=source_type_norm,
statuses=statuses,
requested_horizons=horizons_norm,
limit=safe_limit,
)
else:
signals = self.repo.list_candidate_signals(
signal_id=signal_id_norm,
stock_codes=stock_codes_norm,
market=market_norm,
action=action_norm,
source_type=source_type_norm,
statuses=statuses,
limit=safe_limit,
)
if signal_id_norm is not None and not signals:
raise DecisionSignalNotFoundError(f"Decision signal not found: {signal_id_norm}")
items: List[Dict[str, Any]] = []
created_count = 0
updated_count = 0
skipped_count = 0
for signal in signals:
for horizon in self._horizons_for_signal(signal, horizons_norm):
existing = self.repo.get_outcome(
signal_id=signal.id,
horizon=horizon,
engine_version=DECISION_SIGNAL_OUTCOME_ENGINE_VERSION,
)
if existing is not None and not force and not self._should_recompute_outcome(existing):
skipped_count += 1
items.append(self._serialize_outcome(existing))
continue
View on GitHub (pinned to 5159bd72e8)
Solutions
- Look up valid IDs first: GET /api/v1/decision-signals (list) and use an id from the response.
- Verify the ID exists: check the decision_signals table / repo.get(signal_id).
- Call without signal_id but with stock_codes/market filters to evaluate a batch instead of one signal.
Example fix
# before service.evaluate_outcomes(signal_id=999999) # after signals = service.list_signals(stock_codes=["600519"], limit=5) service.evaluate_outcomes(signal_id=signals[0]["id"])
Defensive patterns
Strategy: try-catch
Validate before calling
signals = service.repo.list_candidate_signals(signal_id=signal_id, limit=1)
if not signals:
return JSONResponse(status_code=404, content={"error": "not_found", "message": f"signal {signal_id} does not exist"})
outcome = service.evaluate_outcomes(signal_id=signal_id) Try / catch
from src.services.decision_signal_service import DecisionSignalNotFoundError
try:
outcome = service.evaluate_outcomes(signal_id=signal_id)
except DecisionSignalNotFoundError:
return JSONResponse(status_code=404, content={"error": "not_found", "message": f"decision signal {signal_id} not found"}) Prevention
- Refresh cached signal IDs after DB resets or deletes.
- Always source ids from the list endpoint in the same environment.
- Treat 404 on this path as an id problem, not a server fault — do not retry blindly.
When it happens
Trigger: POST/GET /api/v1/decision-signals/outcomes (refresh/evaluate) with signal_id that does not exist in decision_signals, e.g. signal_id=999999, or an ID from a different database/environment.
Common situations: Stale signal IDs cached by a client after DB resets, IDs copied from another deployment, or deleted/deduplicated signals; also passing signal_id as a string that normalizes to a different value.
Related errors
- source_report_not_found
- not_found
- not_found
- {field_name} must be an integer
- {field_name} must be positive
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/07f431f497340c8f.
Report an issue: GitHub.