Skip to content

Fix crash on millisecond-scale started_at in hermes agent traces#8313

Open
DaoyuanLi2816 wants to merge 1 commit into
huggingface:mainfrom
DaoyuanLi2816:fix/hermes-trace-millisecond-timestamp
Open

Fix crash on millisecond-scale started_at in hermes agent traces#8313
DaoyuanLi2816 wants to merge 1 commit into
huggingface:mainfrom
DaoyuanLi2816:fix/hermes-trace-millisecond-timestamp

Conversation

@DaoyuanLi2816

Copy link
Copy Markdown
Contributor

Summary

Parsing a hermes-format agent trace whose started_at is expressed in milliseconds crashes with OSError: [Errno 22] Invalid argument.

The bug

src/datasets/packaged_modules/json/json.py normalizes started_at before feeding it to datetime.fromtimestamp (which expects seconds), using a magnitude check to detect whether the input is already in milliseconds:

timestamp = ujson_loads(lines[i])["started_at"]
milliseconds = timestamp if timestamp <= 10_000_000_000 else timestamp * 1_000
sent_at = datetime.fromtimestamp(milliseconds, tz=timezone.utc)...

The large-magnitude branch (timestamp > 10_000_000_000, i.e. already milliseconds) should convert down to seconds by dividing by 1000 — instead it multiplies by 1000 again. For a real millisecond-scale started_at (a common convention, e.g. Date.now()-style timestamps), this produces a value representing a date roughly 56 million years in the future, and datetime.fromtimestamp raises OSError: [Errno 22] Invalid argument on Windows (OverflowError/ValueError on other platforms for the same reason), aborting the whole trace-loading path.

>>> from datetime import datetime, timezone
>>> ts = 1_780_665_768_307  # same instant as the existing seconds-form test fixture, in ms
>>> ms = ts if ts <= 10_000_000_000 else ts * 1_000
>>> datetime.fromtimestamp(ms, tz=timezone.utc)
OSError: [Errno 22] Invalid argument

The fix

Divide instead of multiply, and rename the variable to seconds (what it actually holds, and what datetime.fromtimestamp expects):

timestamp = ujson_loads(lines[i])["started_at"]
seconds = timestamp if timestamp <= 10_000_000_000 else timestamp / 1_000
sent_at = datetime.fromtimestamp(seconds, tz=timezone.utc)...

Tests

Adds HERMES_SESSION_MS — the existing HERMES_SESSION fixture with started_at re-expressed in milliseconds for the same real-world instant — and a new hermes-ms parametrized case in test_json_generate_tables_with_agent_trace_metadata, asserting the exact same sent_at output as the existing seconds-form hermes case.

Verified fail-before / pass-after against the real library (via PYTHONPATH pointed at this checkout, with teich installed so the @require_teich-gated tests actually run): the new hermes-ms case raises OSError before the fix and passes after; the two pre-existing hermes cases are unaffected either way. Full file: 36 passed.

pytest tests/packaged_modules/test_json.py -k hermes

ruff format --check and ruff check are clean.

When parsing hermes-format agent traces, `started_at` is meant to be
normalized to seconds before being passed to `datetime.fromtimestamp`
(which expects seconds), using a magnitude check to detect whether the
input is already in milliseconds:

    milliseconds = timestamp if timestamp <= 10_000_000_000 else timestamp * 1_000

The variable name and the `* 1_000` say "convert to milliseconds", but
`datetime.fromtimestamp` needs *seconds*, and the large-magnitude branch is
exactly the "value is already in milliseconds" case -- it should divide by
1000 to convert down to seconds, not multiply further. For a `started_at`
expressed in milliseconds (a common convention, e.g. `Date.now()`-style
timestamps), multiplying by 1000 again produces a  ~56-million-years-future
timestamp, and `datetime.fromtimestamp` raises `OSError: [Errno 22] Invalid
argument` (or `OverflowError`/`ValueError` on other platforms), aborting the
whole trace-loading path.

Renames the variable to `seconds` (what it actually holds and what
`datetime.fromtimestamp` expects) and fixes the arithmetic to divide.

Adds `HERMES_SESSION_MS` (the existing `HERMES_SESSION` fixture with
`started_at` re-expressed in milliseconds for the same real-world instant)
and a new `hermes-ms` parametrized case in
`test_json_generate_tables_with_agent_trace_metadata`, asserting the same
`sent_at` output as the existing seconds-form hermes case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant