Skip to content

Timeseries TIME_KEY declared TIMESTAMP returns OID 25 text carrying raw epoch millis instead of a timestamp #298

Description

@emanzx

Version / build tested against

origin/main @ 2886155

Deployment mode

Origin — single node (local)

Engine(s) involved

Timeseries

Summary

A timeseries TIME_KEY column declared TIMESTAMP comes back over pgwire as OID 25 (TEXT) carrying the raw epoch-milliseconds integer as a string ('1788692400000'), instead of OID 1114 with a timestamp rendering. Every consumer downstream misreads it: psql displays a bare number, drivers hand applications a string, ORMs fail to map the column to a datetime type, and BI tools cannot treat the time axis as time. The declared DDL type and the wire type disagree — the same fidelity contract that RowDescription preserves for integer widths on other engines is dropped on the timeseries time key.

Steps to reproduce

CREATE COLLECTION tsp (ts TIMESTAMP TIME_KEY, val DOUBLE PRECISION) WITH (engine = 'timeseries');
INSERT INTO tsp (ts, val) VALUES ('2026-09-06T10:00:00Z', 1.5);

SELECT ts, val FROM tsp;
--       ts       | val
-- ---------------+-----
--  1788688800000 | 1.5      <- epoch millis as text; expected 2026-09-06 10:00:00

Driver-level (psycopg2) RowDescription:

cur.execute('SELECT ts, val FROM tsp')
cur.description  -> [('ts', 25), ('val', 701)]     # ts = OID 25 (TEXT); expected 1114 (TIMESTAMP)
cur.fetchone()   -> ('1788692400000', 2.5)         # string of millis

Expected behavior

The wire type follows the declared type: OID 1114 (TIMESTAMP) in RowDescription and a PostgreSQL-format timestamp in the text protocol (2026-09-06 10:00:00), so psql, drivers, and ORMs read the time key as a timestamp. Ingest already accepts the RFC3339 timestamp literal, so the asymmetry is only on the read side.

Actual behavior

RowDescription declares TEXT and the value is the internal epoch-millis representation serialized as a string. Round-tripping a value the server itself accepted (INSERT ... SELECT-style workflows, dump/reload) yields a format the insert path does not document as canonical, and applications must special-case the column.

What actually happened? (check all that are true)

  • Acknowledged/committed data was lost, corrupted, or silently wrong
  • The server crashed, hung, or failed to start
  • A security or isolation boundary was crossed
  • Core functionality is broken with no acceptable workaround
  • A workaround exists (rewrite the query, avoid one path, etc.)

Proposed severity

SEV-3 — Medium: feature wrong, but operational and a workaround exists

Reproducibility

Always — every attempt

Last known-good version / commit (if a regression)

Unknown.

Environment & logs

Linux x86_64, release build from a fresh data directory, trust mode. Tested via psql 16 and psycopg2.

Before submitting

  • I searched existing issues and this is not a duplicate.
  • I reproduced this on a released tag or a current main build (not a stale local branch).
  • This is not a security vulnerability (those go to a private advisory).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:pgwirePostgreSQL wire protocol / client compatengine:timeseriesTimeseries enginepriority:P2Scheduled, not urgentsev:3-mediumFeature wrong, but operational and a workaround existsstatus:needs-triageAwaiting maintainer triage (severity + priority)type:bugA defect — broken, incorrect, or lost data

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions