HKUDS/Vibe-Trading · error · TypeError

'delivery.updated_at' must be an integer (epoch ms) or null

Error message

'delivery.updated_at' must be an integer (epoch ms) or null

What it means

Raised by delivery from_dict (agent/src/scheduled_research/models.py:286) when the optional 'updated_at' field in the delivery object is present but is not an integer. Timestamps are stored as epoch milliseconds (ints); float seconds, ISO strings, or Date objects fail this check. null is accepted.

Source

Thrown at agent/src/scheduled_research/models.py:286

            TypeError: If a present field has the wrong type.
            ValueError: If ``status`` is not a recognized value.
        """
        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
# ---------------------------------------------------------------------------

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Convert to epoch ms int: int(dt.timestamp() * 1000)
  2. Round/convert floats: int(round(value))
  3. Serialize datetimes explicitly to int ms rather than relying on default JSON encoders
  4. Omit the field (null) if you don't track it

Example fix

// before
delivery = {"updated_at": datetime.now(timezone.utc).isoformat()}

// after
from datetime import datetime, timezone
delivery = {"updated_at": int(datetime.now(timezone.utc).timestamp() * 1000)}
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime, timezone

def to_epoch_ms(dt):
    return int(dt.timestamp() * 1000) if dt else None

def updated_at_ok(v):
    return v is None or (isinstance(v, int) and not isinstance(v, bool))

Type guard

from typing import Any, Optional

def as_epoch_ms(value: Any) -> Optional[int]:
    if value is None:
        return None
    if isinstance(value, bool):
        return None
    if isinstance(value, (int, float)):
        return int(value)
    if isinstance(value, str):
        try:
            return int(datetime.fromisoformat(value.replace("Z", "+00:00")).timestamp() * 1000)
        except ValueError:
            return None
    return None

Try / catch

try:
    delivery = DeliveryInfo.from_dict(raw)
except TypeError as exc:
    if "updated_at" in str(exc):
        raw = dict(raw); raw["updated_at"] = None
        delivery = DeliveryInfo.from_dict(raw)
    else:
        raise

Prevention

When it happens

Trigger: delivery = {"updated_at": "2026-01-01T00:00:00Z"} or {"updated_at": 1767225600.5} or {"updated_at": 1767225600000/n} where n makes it a float.

Common situations: Writing epoch seconds instead of milliseconds; serializing datetime objects as ISO strings via a generic JSON encoder; floats creeping in from arithmetic on timestamps.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/ddfe284cf23a64de. Report an issue: GitHub.