Skip to content

aggregator(opencode): iso() throws RangeError on out-of-range server timestamps — one bad session drops every session from that server #2286

Closed

Description

@dezren39

Summary

iso() in the aggregator's OpenCode session mapper converts a server-supplied millisecond timestamp with no range/finite gate, so one session whose time.updated (or time.created) is beyond the valid Date range makes mapServerSessions throw — and every caller fails soft at the whole-server level, so that one bad session silently drops all sessions from that OpenCode server from the attention feed and the durable registry.

Evidence (main 5a34fa70)

  • pm-stack/aggregator/src/sources/opencode.ts:86-87:
    const iso = (ms: number | undefined): string | null =>
      typeof ms === "number" && ms > 0 ? new Date(ms).toISOString() : null;
    typeof + > 0 admit 1e16, Number.MAX_VALUE, and Infinity-adjacent magnitudes. JS Date is only valid to ±8.64e15 ms; new Date(1e16).toISOString() throws RangeError: Invalid Date. (JSON cannot carry Infinity, but it happily carries 1e16.)
  • The throw sites are unguarded: entry construction in mapOne (opencode.ts:174 createdAt: iso(s.time?.created), :179 lastActivityAt: iso(s.time?.updated)) and the long-running-call stamp at :255. mapOne/mapServerSessions have no per-session try/catch — one throw aborts the whole map.
  • The bad session is reliably included before it throws: the attention filter at opencode.ts:146 is now - s.time.updated <= ATTENTION_WINDOW_MS, and for a huge future updated that difference is negative, so the session passes the filter and sorts first (:148).
  • Callers fail soft only at server granularity, which is what turns one bad row into a total loss:
    • pm-stack/aggregator/src/sources/live.ts:878 (attention()) and :983 (registry()): a throw from laptopMapped() is caught and the laptop part is dropped entirely (laptopSeen = false).
    • pm-stack/aggregator/scripts/collect-fleet-feed.ts:456: the sandbox mapServerSessions call sits in a try that leaves attention = [] for the whole sandbox server on throw.

Reproduction (this run)

Sandbox Bun probe driving the real mapServerSessions against a stub v2 server (probe in /tmp/probe-laneB-ociso/probe.ts):

  • Control — one normal session: entries: 1, lastActivityAt stamped correctly.
  • Experiment — the same good session plus one session with time.updated = 1e16: mapServerSessions threw RangeError: Invalid Date; zero entries returned, the good session included.

Why it matters

The timestamps come from a remote OpenCode server's JSON — data this process does not control (a skewed clock, a corrupt store, a different server version). Today a single out-of-range stamp blacks out an entire server's sessions from attention + registry with no error naming the cause: the aggregator just reports the laptop/sandbox source as unreachable/fixtures. Per-session data faults should degrade per-session.

Acceptance criteria

  • iso() (or its callers) returns null for any value that is not a finite, in-Date-range timestamp — no throw for 1e16, Number.MAX_VALUE, or negative/huge magnitudes.
  • One session with an out-of-range time.created/time.updated/message time.created does not prevent the remaining sessions from the same server being mapped (regression test with a mixed good/bad session list against the real mapper, in pm-stack/aggregator/test/opencode.test.ts).
  • Triage pins whether far-future-but-valid stamps (e.g. +1 year) also count as "fresh" in the :146 attention filter, or whether that stays as-is — record the decision on this issue.
  • Existing aggregator tests pass.

Dedup

Checked open + closed issues for mapServerSessions, "opencode iso", "toISOString throws": no existing issue covers this mapper. #2196 is quota-extract's monthDayTime throw (different file/mechanism); #1540/#2253/#2264 are store/quota/snapshot date gates, distinct modules.

Activity

  1. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    effort/xsTrivial: expected under 30 minutes of work
    on Oct 29, 2026
  3. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator-code-b
    • Session / ID: new-issue-creator-code-b cron run 2026-10-29 06:50 CDT
    • Found via: filed this run
    • Task: Filed: aggregator opencode mapper iso() (opencode.ts:86-87) has no Date-range gate — a server session with time.updated=1e16 throws RangeError in mapOne and both production callers fail soft per-server, dropping every session from that server. Verified with a sandbox Bun probe driving the real mapServerSessions against a stub v2 server (control 1 entry; mixed list threw, 0 entries).
    • Expectation: effort xs; done when iso() returns null for non-finite/out-of-range stamps, a mixed good/bad session list still maps the good sessions, and triage pins the far-future attention-filter question.
    • Links: evidence body hidden_files/issue-code-opencode-iso-range-body.md; probe /tmp/probe-laneB-ociso/probe.ts
  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 31, 2026
  5. 11 remaining items

  6. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 31, 2026
  7. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: parked
    task: 4327 (lane E)
    pr: #3093 @ 8de9397
    note: Implemented per pinned decisions: shared validMs predicate (finite, 0 < ms <= 8.64e15) inside iso() and the freshness inclusion; no per-session try/catch; far-future-valid stays fresh. bun test test/opencode.test.ts on laptop: 4 pass, 0 fail (new mixed good/bad regression). Parked for CI + Codex review; resume: CI green + Codex clean -> merge -> close this issue.

  8. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Oct 31, 2026
  9. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    Lane D picked up task 4327 — resuming PR 3093. Fresh check: head 8de9397 matches the checkpoint, Codex review COMPLETED on that head with no findings, diff verified (validMs gates both iso() and the freshness inclusion; regression tests for 1e16 updated/created). Aggregator PRs get no Actions CI, so verification is the laptop aggregator suite before merge.

  10. added a commit that references this issue on Oct 31, 2026
  11. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    Done — PR 3093 merged (2ac4f4c). Codex clean on 8de9397; laptop verification: opencode.test.ts 4/4 pass; full aggregator suite 691 pass with 7 manifest/page failures proven identical on clean main (pre-existing, unrelated). Task 4327 completed fixed_merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)effort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions