ZhuLinsen/daily_stock_analysis · error · ValueError
trigger_source is required
Error message
trigger_source is required
What it means
ValueError from DecisionSignalService._normalize_trigger_source (src/services/decision_signal_service.py:1182): after running the value through _public_text (sanitize + max_length=64), the text is empty, so trigger_source — a required field — is effectively missing. Empty-but-present input, whitespace-only input, or input that sanitization reduces to empty all land here; None input fails earlier inside _public_text with 'trigger_source is required'.
Source
Thrown at src/services/decision_signal_service.py:1182
raise ValueError(f"{field_name} must be one of {allowed_text}")
return text
@classmethod
def _normalize_optional_enum(
cls,
value: Any,
allowed: frozenset[str],
field_name: str,
) -> Optional[str]:
if value in (None, ""):
return None
return cls._normalize_enum(value, allowed, field_name)
@staticmethod
def _normalize_trigger_source(value: Any) -> str:
text = DecisionSignalService._public_text(value, "trigger_source", max_length=64, required=True)
if not text:
raise ValueError("trigger_source is required")
return text
@classmethod
def _normalize_optional_trigger_source(cls, value: Any) -> Optional[str]:
if value in (None, ""):
return None
return cls._normalize_trigger_source(value)
@staticmethod
def _optional_text(value: Any, field_name: str, *, max_length: int) -> Optional[str]:
if value is None:
return None
text = str(value).strip()
if not text:
return None
if len(text) > max_length:
raise ValueError(f"{field_name} must be at most {max_length} characters")
return textView on GitHub (pinned to 5159bd72e8)
Solutions
- Set an explicit non-empty trigger_source per producer, e.g. 'scheduled_scan', 'manual', 'price_alert' (≤64 chars).
- Default it at the call site: payload.setdefault('trigger_source', 'manual') before create_signal.
- If sanitization is eating the value, send plain text without markup/control characters.
- Add it to the client-side required-field validation.
Example fix
# before
service.create_signal({"stock_code": "600519", "market": "cn", "action": "buy", "trigger_source": ""}) # ValueError
# after
service.create_signal({"stock_code": "600519", "market": "cn", "action": "buy", "trigger_source": "scheduled_scan"}) Defensive patterns
Strategy: validation
Validate before calling
trigger = str(payload.get('trigger_source') or '').strip()
if not trigger:
payload['trigger_source'] = 'manual' # or reject early with a clear client-side error Type guard
def has_trigger_source(payload: dict) -> bool:
return bool(str(payload.get('trigger_source') or '').strip()) Prevention
- Use short fixed literals per producer ('scheduled_scan', 'manual') so trigger_source is never blank.
- Don't build payloads with falsy-filtering dict comprehensions; use `is not None`.
- Include trigger_source in client-side required-field checks.
When it happens
Trigger: create-signal payloads with trigger_source: '', ' ', or content consisting only of characters stripped by sanitize_decision_signal_text (e.g. control chars/markup). Bulk pipelines templating trigger_source from a variable that is occasionally blank.
Common situations: Optional-looking field actually required; ingestion code using a per-source constant that a refactor renamed to None/''; sanitization stripping HTML wrappers leaving nothing; test fixtures omitting the field.
Related errors
- stock_code is required
- {field_name} is required
- {field_name} must be an integer
- {field_name} must be positive
- unsupported_report_type
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/5656436fc7f0a95c.
Report an issue: GitHub.