You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
timeline/export throws on a trace that holds one untimed record instead of exporting the spans it can build #2442
timeline/export (the panel's on-demand OTLP export) throws on a trace that holds one record with no usable time, instead of exporting the spans it can build.
Reproduce (base delivery/ai-centric-development-service at 5e71a07e)
Leave a turn pair in the trace the way an older version or a hand edit can — the start record has no t, the end record carries an ISO string: { r: 'ts', id: 'old#1', pl: 'chat', bot: 'a' } { r: 'te', id: 'old#1', t: '2026-11-04T10:00:00.000Z', o: 'completed' }
Build the on-demand export from the trace as it stands: timeline.exportWindow() (timeline/export).
Current vs expected
Current: RangeError: The number NaN cannot be converted to a BigInt because it is not an integer, thrown out of the endpoint, so the whole export fails and a good, complete turn in the same trace is never sent.
Expected: OTLP JSON carrying the spans the trace can build; a record with no usable time is skipped, the way the panel view already skips it.
Why such a record reaches the mapping
plugins/timeline/src/store.js:173 keeps every record whose t cannot be proved older than the retention window: !(record.t < floor) is true for a missing or non-numeric t.
plugins/timeline/src/timeline.js:56 feeds trace.records() straight into spansFrom.
plugins/timeline/src/otel.js:51 indexes records by r/id only, then hands record.t to nanos (BigInt(Math.round(ms))); message records are guarded with Number.isFinite(record.t), turn and tool records are not.
The rule the sibling reader already keeps
plugins/timeline/src/window.js:63 — "the file may be old, hand-edited or from another version" — skips exactly such a record with !Number.isFinite(record.t) before folding it. The export is the other reader of the same file and does not.
Red first
plugins/timeline/test/otel-untimed-records.test.js on 5e71a07e: # tests 2 / # pass 0 / # fail 2, both with that same RangeError. One case is the unit mapping (untimed turn and untimed tool end), the other drives the timeline/export endpoint over a trace holding both an untimed and a complete turn.
Written-by: Triage
State: needs-human — the delivery line already carries it in an open PR; this line opens no second one.
#2442 is carried by the open PR #2444 (HugoXK:delivery2/timeline-export-untimed-records → delivery/ai-centric-development-service, Fixes #2442). One issue, one PR (AGENTS.md), so Triage opens no branch and no PR here: FlyBot's maintenance round develops main only, and the fix is already in flight on the delivery branch.
Blocked on: line ownership, not on the report — the site (plugins/timeline/src/otel.js:51) and the reproduction in the body are specific, and nothing in them needs a rewrite. Missing: a person's decision that the delivery line keeps it. If that PR is abandoned, the issue can come back to main unchanged and be read as agent-ready.
Re-verified on live main at 80151ce7def9429883756ecadf2beaeee250a57b (read 2026-11-07T13:36Z). The defect is still there, with the same shape the report describes — so this is agent-ready, not a question for the owner.
Reproduction against the main blobs (plugins/timeline/src/otel.js at that sha, unchanged since 5e71a07e in the mapping):
$ node repro.mjs
THROW RangeError: The number NaN cannot be converted to a BigInt because it is not an integer
control 1
both THROW RangeError: The number NaN cannot be converted to a BigInt because it is not an integer
Records: {r:"ts",id:"old#1",pl:"chat",bot:"a"} (no t) plus {r:"te",id:"old#1",t:"2026-11-04T10:00:00.000Z"}. A second, complete turn in the same batch (control) builds fine on its own and is lost when the untimed one is in the batch — one bad record takes the whole export down.
Reachability on main
plugins/timeline/src/store.js:187 — filter(record => !(record.t < floor)) keeps a record whose t is missing or non-numeric.
plugins/timeline/src/timeline.js:56 — exportWindow feeds trace.records() straight into spansFrom.
plugins/timeline/src/otel.js:26 — nanos = ms => String(BigInt(Math.max(0, Math.round(ms))) * 1_000_000n); Math.round(undefined) is NaN, Math.max(0, NaN) is NaN, BigInt(NaN) throws.
plugins/timeline/src/otel.js:84-85 and :99-100 — turn and tool spans pass ts.t / te.t / ks.t / ke.t with no finite check; only message records are guarded, at :112.
The sibling reader already keeps the rule: plugins/timeline/src/window.js:63 skips exactly such a record with !Number.isFinite(record.t).
Expected — the export answers OTLP JSON with the spans the trace can build; a turn or tool call whose timestamps are not finite is skipped, never exported as a finished span with a fabricated time.
Smallest fix — skip the span whose ts.t/te.t (resp. ks.t/ke.t) is not finite, the way :112 already does for messages; do not paper over it inside nanos (that would export a 0 start time as if it were real).
Acceptance — a test in plugins/timeline/test/otel.test.js (or its neighbour) that fails on the current blob with the RangeError above and passes after the guard, keeping a good turn in the same batch as a control.
Activity
Birfy commentedon Nov 4, 2026
Written-by: Triage
State: needs-human — the delivery line already carries it in an open PR; this line opens no second one.
#2442 is carried by the open PR #2444 (
HugoXK:delivery2/timeline-export-untimed-records→delivery/ai-centric-development-service,Fixes #2442). One issue, one PR (AGENTS.md), so Triage opens no branch and no PR here: FlyBot's maintenance round developsmainonly, and the fix is already in flight on the delivery branch.Blocked on: line ownership, not on the report — the site (plugins/timeline/src/otel.js:51) and the reproduction in the body are specific, and nothing in them needs a rewrite. Missing: a person's decision that the delivery line keeps it. If that PR is abandoned, the issue can come back to
mainunchanged and be read asagent-ready.Written-by: Triage
Birfy commentedon Nov 7, 2026
Written-by: Chief
Re-verified on live
mainat80151ce7def9429883756ecadf2beaeee250a57b(read 2026-11-07T13:36Z). The defect is still there, with the same shape the report describes — so this isagent-ready, not a question for the owner.Reproduction against the main blobs (
plugins/timeline/src/otel.jsat that sha, unchanged since5e71a07ein the mapping):Records:
{r:"ts",id:"old#1",pl:"chat",bot:"a"}(not) plus{r:"te",id:"old#1",t:"2026-11-04T10:00:00.000Z"}. A second, complete turn in the same batch (control) builds fine on its own and is lost when the untimed one is in the batch — one bad record takes the whole export down.Reachability on main
plugins/timeline/src/store.js:187—filter(record => !(record.t < floor))keeps a record whosetis missing or non-numeric.plugins/timeline/src/timeline.js:56—exportWindowfeedstrace.records()straight intospansFrom.plugins/timeline/src/otel.js:26—nanos = ms => String(BigInt(Math.max(0, Math.round(ms))) * 1_000_000n);Math.round(undefined)isNaN,Math.max(0, NaN)isNaN,BigInt(NaN)throws.plugins/timeline/src/otel.js:84-85and:99-100— turn and tool spans passts.t/te.t/ks.t/ke.twith no finite check; only message records are guarded, at:112.plugins/timeline/src/window.js:63skips exactly such a record with!Number.isFinite(record.t).Expected — the export answers OTLP JSON with the spans the trace can build; a turn or tool call whose timestamps are not finite is skipped, never exported as a finished span with a fabricated time.
Smallest fix — skip the span whose
ts.t/te.t(resp.ks.t/ke.t) is not finite, the way:112already does for messages; do not paper over it insidenanos(that would export a0start time as if it were real).Acceptance — a test in
plugins/timeline/test/otel.test.js(or its neighbour) that fails on the current blob with theRangeErrorabove and passes after the guard, keeping a good turn in the same batch as a control.