HKUDS/Vibe-Trading · error · ValueError

{model}: generated_at must be timezone-aware (e.g. datetime.

Error message

{model}: generated_at must be timezone-aware (e.g. datetime.now(timezone.utc)), got a naive datetime {value!r} -- an artifact's timestamp must be unambiguous.

What it means

generated_at must be timezone-aware: a datetime whose tzinfo or utcoffset() is None is rejected. Naive timestamps are ambiguous across systems and would make artifact ordering and hashing non-reproducible, hence the ValueError.

Source

Thrown at agent/src/quantlib/valuation/artifact.py:358

    Args:
        value: The candidate ``generated_at``.
        model: Name of the calling builder, for the error message.

    Returns:
        ``value`` unchanged.

    Raises:
        TypeError: If ``value`` is not a ``datetime.datetime``.
        ValueError: If ``value`` is timezone-naive.
    """
    if not isinstance(value, datetime):
        raise TypeError(
            f"{model}: generated_at must be a datetime.datetime supplied by the "
            f"caller, got {type(value).__name__}. This module never calls "
            "datetime.now() -- pass datetime.now(timezone.utc) yourself."
        )
    if value.tzinfo is None or value.utcoffset() is None:
        raise ValueError(
            f"{model}: generated_at must be timezone-aware (e.g. "
            "datetime.now(timezone.utc)), got a naive datetime "
            f"{value!r} -- an artifact's timestamp must be unambiguous."
        )
    return value


# ---------------------------------------------------------------------------
# Canonical normalization: numbers, then the recursive flatten/hash engine
# ---------------------------------------------------------------------------


def _normalize_number(value: float) -> str:
    """Canonicalise one number for hashing.

    Fixed 12-significant-digit scientific notation, independent of magnitude,
    so ``int`` and ``float`` inputs representing the same economic value hash
    identically, and ``-0.0`` collapses to ``0.0``. 12 significant digits is

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use datetime.now(timezone.utc).
  2. Attach a timezone: value.replace(tzinfo=timezone.utc) only when you know the value is UTC; otherwise use zoneinfo to localize correctly.
  3. When parsing ISO strings, ensure they include an offset (e.g. '2026-01-01T00:00:00+00:00').

Example fix

# before
build_dcf_artifact(generated_at=datetime(2026, 1, 1), ...)
# after
from datetime import datetime, timezone
build_dcf_artifact(generated_at=datetime(2026, 1, 1, tzinfo=timezone.utc), ...)
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime, timezone
if isinstance(generated_at, datetime) and generated_at.tzinfo is None:
    generated_at = generated_at.replace(tzinfo=timezone.utc)  # only if value is known UTC

Type guard

from datetime import datetime
def is_timezone_aware(dt) -> bool:
    return isinstance(dt, datetime) and dt.tzinfo is not None and dt.utcoffset() is not None

Prevention

When it happens

Trigger: build_dcf_artifact(generated_at=datetime(2026, 1, 1), ...) with no tzinfo; datetime.fromisoformat("2026-01-01T00:00:00") which yields a naive datetime; a database driver returning naive datetimes.

Common situations: SQLite/CSV/JSON round-trips that strip timezones; test fixtures with naive datetimes; pandas Timestamps converted without tz.

Related errors


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