Skip to content

search(postgres): _lastUpdated returns 500 on every prefix and precision #871

Description

@angela-helios

Found in the #448 Postgres leg. Every _lastUpdated search fails with an opaque 500 on the Postgres backend — all precisions (2026-09-01, 2026-09-01T00:00:00Z) and all prefixes (eq/gt/ge/le):

GET /Patient?_lastUpdated=2026-09-02          → 500
GET /Patient?_lastUpdated=gt2026-09-01T00:00:00Z → 500

Server log:

ERROR helios_rest::error: internal error while processing request
  error.detail=internal error in postgres: Failed to execute search: error serializing parameter 2

Cause

build_last_updated_condition (crates/persistence/src/backends/postgres/search/query_builder.rs:645) binds the raw query string as a text parameter directly against the last_updated column:

conditions.push(SqlFragment::with_params(
    format!("last_updated {} ${}", op, param_num),
    vec![SqlParam::text(&value.value)],
));

last_updated is TIMESTAMPTZ, and tokio-postgres refuses to serialize a text param into it — hence "error serializing parameter 2" on every query.

Two layers to fix:

  1. Bind a real timestamp (or cast) so the query executes at all.
  2. Apply the same precision-range semantics the date-parameter path already has (the range helper at the top of the same file): eq at day precision must mean >= day AND < day+1, not a text =. The fix(search): normalize sqlite date comparisons across precisions #463 date fix explicitly covered _lastUpdated's separate code path on SQLite; Postgres needs the equivalent.

SQLite answers the same queries correctly. The #448 battery runs 22 checks on this backend; these are the only 2 failures.

Activity

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions