ZhuLinsen/daily_stock_analysis · warning · DecisionSignalReassessGuardrailBlockedError
guardrail_blocked
guardrail_blocked
Error message
actionable_signal_blocked_by_guardrail
What it means
When persist=True, the reassess flow first runs the decision policy guardrail; if policy.guardrail_result.passed is False it raises DecisionSignalReassessGuardrailBlockedError with blocked_reason (defaulting to 'actionable_signal_blocked_by_guardrail') and warnings. This prevents persisting signals that violate actionable-signal policy (e.g. insufficient confidence/data quality).
Source
Thrown at src/services/decision_signal_reassess_service.py:127
"target_price": preview_candidate.target_price,
"invalidation": preview_candidate.invalidation,
"reason": preview_candidate.reason,
"risk_summary": preview_candidate.risk_summary,
"watch_conditions": preview_candidate.watch_conditions,
"metadata": metadata,
}
if not persist:
return {
"preview": preview,
"item": None,
"created": False,
"persist_status": None,
"warnings": policy.warnings,
"blocked_reason": policy.blocked_reason,
}
if not policy.guardrail_result.passed:
raise DecisionSignalReassessGuardrailBlockedError(
blocked_reason=policy.blocked_reason or "actionable_signal_blocked_by_guardrail",
warnings=policy.warnings,
)
payload = _build_persist_payload(
record,
raw_result=raw_result,
decision_profile=decision_profile_norm,
candidate=preview_candidate,
metadata=metadata,
)
market_phase_summary = _as_mapping(context_snapshot.get("market_phase_summary"))
if not market_phase_summary:
market_phase_summary = _as_mapping(raw_result.get("market_phase_summary"))
try:
outcome = self.signal_service.create_history_bound_signal_with_outcome(
payload,
history_created_at=getattr(record, "created_at", None),View on GitHub (pinned to 5159bd72e8)
Solutions
- Call with persist=false first and inspect preview + blocked_reason/warnings to see which guardrail failed.
- Choose a different decision_profile whose rules the report satisfies, or fix the underlying data-quality issue in the report.
- Do not persist blocked candidates; treat the exception as the intended policy outcome.
Example fix
# before result = service.reassess(source_report_id=rid, decision_profile="aggressive", persist=True) # after preview = service.reassess(source_report_id=rid, decision_profile="aggressive", persist=False) print(preview["blocked_reason"], preview["warnings"]) # fix inputs/profile, then persist=True
Defensive patterns
Strategy: try-catch
Validate before calling
preview = service.reassess(source_report_id=rid, decision_profile=profile, persist=False)
if preview.get("blocked_reason"):
return JSONResponse(status_code=422, content={"error": "guardrail_blocked", "blocked_reason": preview["blocked_reason"], "warnings": preview["warnings"]})
result = service.reassess(source_report_id=rid, decision_profile=profile, persist=True) Try / catch
from src.services.decision_signal_reassess_service import DecisionSignalReassessGuardrailBlockedError
try:
result = service.reassess(source_report_id=rid, decision_profile=profile, persist=True)
except DecisionSignalReassessGuardrailBlockedError as exc:
return JSONResponse(status_code=422, content={"error": "guardrail_blocked", "blocked_reason": exc.blocked_reason, "warnings": exc.warnings}) Prevention
- Always run persist=false preview first and check blocked_reason before persisting.
- Treat guardrail blocks as policy outcomes, not bugs — never retry with persist=true unchanged.
- Keep guardrail policy config under test so profile changes that block reports are caught early.
When it happens
Trigger: POST reassess with persist=true on a report whose policy evaluation fails the guardrail — low score, missing data-quality prerequisites, or profile-specific rules; preview-only calls (persist=false) return blocked_reason instead of raising.
Common situations: Trying to materialize signals from weak/ambiguous reports; changing guardrail policy config so previously persistable reports now fail; batch-reassessing old reports under a stricter profile.
Related errors
- source_report_not_found
- unsupported_report_snapshot
- unsupported_report_type
- not_found
- {field_name} must be an integer
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/af9846db19b7fa27.
Report an issue: GitHub.