Skip to content

fix(time-series): return a null sample from TS.MGET for an empty series - #3530

Merged
nkaradzhov merged 1 commit into
redis:masterfrom
maxymlyskov:fix/ts-mget-null-sample-for-empty-series
Oct 23, 2026
Merged

nkaradzhov merged 1 commit into
redis:masterfrom
maxymlyskov:fix/ts-mget-null-sample-for-empty-series

Conversation

@maxymlyskov

@maxymlyskov maxymlyskov commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Description

Fixes #3528

For a series that exists but has no samples yet, TS.MGET sends an empty sample ([]), and transformSampleReply destructures [timestamp, value] from it anyway. So ts.mGet(), ts.mGetWithLabels() and ts.mGetSelectedLabels() return a sample with an undefined timestamp for that key. On master, redis 8.10.2, with one empty and one written series under the same label:

RESP2 ts.mGet -> { 'h3t:empty': { sample: { timestamp: undefined, value: NaN } }, 'h3t:full': { sample: { timestamp: 1000, value: 5 } } }
RESP3 ts.mGet -> { 'h3t:empty': { sample: { timestamp: undefined, value: undefined } }, 'h3t:full': { sample: { timestamp: 1000, value: 5 } } }

and with this branch:

RESP2 ts.mGet -> { 'h3t:empty': { sample: null }, 'h3t:full': { sample: { timestamp: 1000, value: 5 } } }
RESP3 ts.mGet -> { 'h3t:empty': { sample: null }, 'h3t:full': { sample: { timestamp: 1000, value: 5 } } }

TS.GET already returns null for the same empty reply, so the MGET commands now do the same, as agreed in the issue.

Added transformNullableSampleReply next to transformSampleReply in helpers.ts. It returns null for an empty sample and otherwise calls transformSampleReply. MGET and createTransformMGetLabelsReply (MGET_WITHLABELS, reused by MGET_SELECTED_LABELS) use it. The declared sample type on the three commands is now { timestamp, value } | null, the same as TS.GET's.

transformSampleReply and transformSamplesReply don't change, so RANGE, REVRANGE, READ and the MRANGE variants keep their types.

Added a RESP2/RESP3 test in each of MGET.spec.ts, MGET_WITHLABELS.spec.ts and MGET_SELECTED_LABELS.spec.ts: a labelled series with no samples, and sample should be null. All 6 fail on master.

npm run build && npm test passes (time-series 196, client 3541), lint is clean.


Checklist

  • Does npm test pass with this change (including linting)?
  • Is the new or changed code fully tested?
  • Is a documentation update included (if this change modifies existing APIs, or introduces new ones)?

Note

Low Risk
Localized reply-transform change with tests; no auth or persistence impact, and RANGE/MGET sample paths stay on the non-nullable transformer.

Overview
TS.MGET family commands now return sample: null when a matched time series exists but has no data points, instead of a broken object with undefined timestamp and NaN/undefined value.

A new transformNullableSampleReply helper treats an empty [] sample from Redis as null and otherwise uses the existing sample transformer. mGet, mGetWithLabels, and mGetSelectedLabels wire this in for RESP2 and RESP3, matching TS.GET behavior (fixes #3528). RANGE/MRANGE-style commands are unchanged.

Integration tests cover an empty labelled series for both RESP versions on all three MGET variants.

Reviewed by Cursor Bugbot for commit 73a80a4. Bugbot is set up for automated code reviews on this repo. Configure here.

For a series that exists but has no samples yet, TS.MGET sends an empty
sample. transformSampleReply destructured it anyway, so mGet(),
mGetWithLabels() and mGetSelectedLabels() returned
{ timestamp: undefined, value: NaN } on RESP2 and both fields undefined on
RESP3, which reads as a measurement. TS.GET on the same key returns null.

Add transformNullableSampleReply, which returns null for an empty sample,
as TS.GET does, and use it on the MGET path only. transformSampleReply
stays non-null, so RANGE, MRANGE and READ keep their types.

Fixes redis#3528
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-22T15:01:31.684897Z 73a80a4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@nkaradzhov nkaradzhov left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@nkaradzhov
nkaradzhov merged commit 6377325 into redis:master Oct 23, 2026
25 of 26 checks passed
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.

ts.mGet() returns a sample with an undefined timestamp for a series that has no samples yet

2 participants