HKUDS/Vibe-Trading · error · TypeError
'delivery.attempts' must be a non-negative integer
Error message
'delivery.attempts' must be a non-negative integer
What it means
Raised by delivery from_dict (agent/src/scheduled_research/models.py:289) when the 'attempts' field in the delivery object is a bool, a non-int, or a negative int. The bool check exists because isinstance(True, int) is True in Python, so explicit rejection is needed. Defaults to 0 when absent.
Source
Thrown at agent/src/scheduled_research/models.py:289
if not data:
return cls()
if not isinstance(data, dict):
raise TypeError("'delivery' must be an object or null")
raw_status = data.get("status", DeliveryStatus.NONE.value)
try:
status = DeliveryStatus(raw_status)
except ValueError as exc:
raise ValueError(f"unknown delivery status {raw_status!r}") from exc
for name in ("session_id", "key", "error", "provider_message_id"):
value = data.get(name)
if value is not None and not isinstance(value, str):
raise TypeError(f"'delivery.{name}' must be a string or null")
updated_at = data.get("updated_at")
if updated_at is not None and not isinstance(updated_at, int):
raise TypeError("'delivery.updated_at' must be an integer (epoch ms) or null")
attempts = data.get("attempts", 0)
if isinstance(attempts, bool) or not isinstance(attempts, int) or attempts < 0:
raise TypeError("'delivery.attempts' must be a non-negative integer")
return cls(
status=status,
session_id=data.get("session_id"),
key=data.get("key"),
error=data.get("error"),
attempts=attempts,
updated_at=updated_at,
provider_message_id=data.get("provider_message_id"),
)
# ---------------------------------------------------------------------------
# Data model
# ---------------------------------------------------------------------------
def _verdict_record_or_none(data: Any, job_id: str) -> Optional[VerdictRecord]:
"""Parse a persisted last_verdict, degrading an unreadable one to None.View on GitHub (pinned to 80ffdda44c)
Solutions
- Clamp retry counters: max(0, int(attempts))
- Keep attempts as int through all retry arithmetic
- Omit the field to use the default of 0
Example fix
// before
delivery = {"attempts": attempts - 1} # can reach -1
// after
delivery = {"attempts": max(0, attempts - 1)} Defensive patterns
Strategy: validation
Validate before calling
def attempts_ok(v):
return not isinstance(v, bool) and isinstance(v, int) and v >= 0 Type guard
def safe_attempts(v, default=0):
if isinstance(v, bool) or not isinstance(v, int) or v < 0:
return default
return v Try / catch
try:
delivery = DeliveryInfo.from_dict(raw)
except TypeError as exc:
if "attempts" in str(exc):
raw = dict(raw); raw["attempts"] = 0
delivery = DeliveryInfo.from_dict(raw)
else:
raise Prevention
- Clamp retry counters with max(0, n) on every decrement
- Keep counters as ints; never store flags in numeric fields
- Round-trip test your persisted records
When it happens
Trigger: delivery = {"attempts": -1}, {"attempts": "3"}, {"attempts": 2.0}, or {"attempts": True}. All four hit the combined isinstance/bool/negative guard.
Common situations: Decrementing attempts below zero in retry logic; JSON round-tripping ints as strings; flags accidentally stored in the attempts slot; floats after division-based backoff math.
Related errors
- 'delivery' must be an object or null
- 'delivery.{name}' must be a string or null
- 'id', 'prompt', and 'schedule' must be strings
- 'consecutive_failures' must be a non-negative integer
- 'last_error' must be a string or null
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/d782ae66c3697be1.
Report an issue: GitHub.