ZhuLinsen/daily_stock_analysis · error · ValueError
invalid ttl_hours: {ttl_hours}
Error message
invalid ttl_hours: {ttl_hours} What it means
Raised when an optional 'ttl_hours' field on an alert rule is present but cannot be coerced to float (TypeError for None/list/dict, ValueError for non-numeric strings). ttl_hours controls how long the rule lives before expiring; it is optional, but a present value must be numeric so remove_expired and TTL arithmetic work.
Source
Thrown at src/agent/events.py:490
try:
alert_type = AlertType(rule.get("alert_type", ""))
except ValueError as exc:
raise ValueError(f"invalid alert_type: {rule.get('alert_type')}") from exc
_ensure_runtime_supported_alert_type(alert_type)
status = rule.get("status")
if status is not None:
try:
AlertStatus(status)
except ValueError as exc:
raise ValueError(f"invalid status: {status}") from exc
ttl_hours = rule.get("ttl_hours")
if ttl_hours is not None:
try:
ttl_value = float(ttl_hours)
except (TypeError, ValueError) as exc:
raise ValueError(f"invalid ttl_hours: {ttl_hours}") from exc
if ttl_value <= 0:
raise ValueError("ttl_hours must be > 0")
if alert_type == AlertType.PRICE_CROSS:
direction = str(rule.get("direction", "above")).lower()
if direction not in {"above", "below"}:
raise ValueError(f"invalid direction: {direction}")
try:
price = float(rule.get("price"))
except (TypeError, ValueError) as exc:
raise ValueError(f"invalid price: {rule.get('price')}") from exc
if price <= 0:
raise ValueError("price must be > 0")
elif alert_type == AlertType.PRICE_CHANGE_PERCENT:
direction = str(rule.get("direction", "up")).lower()
if direction not in {"up", "down"}:
raise ValueError(f"invalid direction: {direction}")
try:View on GitHub (pinned to 5159bd72e8)
Solutions
- Provide ttl_hours as a number (or numeric string) of hours, e.g. 24 or '24.0'.
- Convert human units (days/minutes) to hours before building the rule dict.
- Omit the key if you want the default TTL behavior.
Example fix
// before
rule = {"stock_code": "AAPL", "alert_type": "volume_spike", "ttl_hours": "24h"}
# ValueError: invalid ttl_hours: 24h
// after
rule = {"stock_code": "AAPL", "alert_type": "volume_spike", "ttl_hours": 24}
validate_event_alert_rule(rule) Defensive patterns
Strategy: validation
Validate before calling
def valid_ttl(raw) -> bool:
if raw is None:
return True
try:
float(raw)
return True
except (TypeError, ValueError):
return False Type guard
def has_numeric_ttl(rule: dict) -> bool:
return valid_ttl(rule.get("ttl_hours")) Try / catch
try:
validate_event_alert_rule(rule)
except ValueError as e:
if str(e).startswith("invalid ttl_hours"):
rule.pop("ttl_hours", None) or reject(rule) Prevention
- Author ttl_hours as plain numbers, never strings with units.
- Convert '1 day' style input to hours before building the rule.
- Leave the key absent rather than sending null-ish strings.
When it happens
Trigger: validate_event_alert_rule with rule['ttl_hours'] = 'forever', None, [24], {}, or a string like '24h' (float('24h') raises). Numeric strings such as '24' or 24.0 are fine. Omitting the key skips the check.
Common situations: Rules authored with human units ('1 day', '24h') instead of hours as a number; JSON round-trips where null replaced an omitted key is safe here, but empty string '' fails; LLM-generated TTLs in prose form.
Related errors
- ttl_hours must be > 0
- invalid price: {rule.get('price')}
- unsupported alert_type for current EventMonitor runtime: {al
- stock_code is required
- invalid alert_type: {rule.get('alert_type')}
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/3d964989ca16e9e7.
Report an issue: GitHub.