Summary
Version: 1.9.19 (FOSS build, installed via Obtainium)
Android: Pixel 8
Feature: Local HTTP server, GET /?days=N
Summary
The oldest step bucket returned by GET /?days=N covers only the elapsed
hours within the requested window, but its start_time is set to local
midnight — so it looks like a complete day and is not. Every other bucket in
the response is correct.
Consumers that key on start_time will silently store a partial count as a
full day.
Workaround
Request N+1 days and discard the oldest bucket.
Steps to reproduce
Three requests made within seconds of each other, ~23:35 local:
?days=2
2026-09-04T07:00:00Z 1632 <-- oldest bucket
2026-09-05T07:00:00Z 14385
2026-09-06T07:00:00Z 8984
?days=4
2026-09-02T07:00:00Z 363 <-- oldest bucket
2026-09-03T07:00:00Z 6722
2026-09-04T07:00:00Z 5824 <-- same day, now complete
2026-09-05T07:00:00Z 14385
2026-09-06T07:00:00Z 8984
?days=7
2026-08-30T07:00:00Z 762 <-- oldest bucket
...
2026-09-02T07:00:00Z 6096 <-- same day, now complete
2026-09-04T07:00:00Z 5824
2026-09-05T07:00:00Z 14385
Sept 4 reads 1632 as the boundary bucket and 5824 otherwise.
Sept 2 reads 363 as the boundary bucket and 6096 otherwise.
Aug 30 reads 762 as the boundary bucket and 9160 when the window is widened.
Non-boundary days are identical across all window sizes.
Expected behavior
Either the oldest bucket's start_time reflects the actual window start
rather than local midnight, or the window is snapped to midnight so the
bucket really is a full day. Either would let consumers trust the label.
Actual behavior
The oldest bucket in the response carries a start_time of local midnight,
implying a full day, but its count only covers the hours that fall inside
the requested window. The same calendar day returns a larger, correct count
as soon as it is no longer the oldest bucket in the window.
A consumer storing count keyed on the date of start_time therefore records
a partial day as a complete one, with no indication in the payload that it is
incomplete.
Environment
Device: Google Pixel 8
Android: 17
App: HC Webhook 1.9.19 (FOSS build via Obtainium)
Health Connect: system provided
Network: local HTTP server on port 8787, accessed over Tailscale
Checklist
Summary
Version: 1.9.19 (FOSS build, installed via Obtainium)
Android: Pixel 8
Feature: Local HTTP server,
GET /?days=NSummary
The oldest step bucket returned by
GET /?days=Ncovers only the elapsedhours within the requested window, but its
start_timeis set to localmidnight — so it looks like a complete day and is not. Every other bucket in
the response is correct.
Consumers that key on
start_timewill silently store a partial count as afull day.
Workaround
Request N+1 days and discard the oldest bucket.
Steps to reproduce
Three requests made within seconds of each other, ~23:35 local:
Sept 4 reads 1632 as the boundary bucket and 5824 otherwise.
Sept 2 reads 363 as the boundary bucket and 6096 otherwise.
Aug 30 reads 762 as the boundary bucket and 9160 when the window is widened.
Non-boundary days are identical across all window sizes.
Expected behavior
Either the oldest bucket's
start_timereflects the actual window startrather than local midnight, or the window is snapped to midnight so the
bucket really is a full day. Either would let consumers trust the label.
Actual behavior
The oldest bucket in the response carries a
start_timeof local midnight,implying a full day, but its
countonly covers the hours that fall insidethe requested window. The same calendar day returns a larger, correct count
as soon as it is no longer the oldest bucket in the window.
A consumer storing
countkeyed on the date ofstart_timetherefore recordsa partial day as a complete one, with no indication in the payload that it is
incomplete.
Environment
Device: Google Pixel 8
Android: 17
App: HC Webhook 1.9.19 (FOSS build via Obtainium)
Health Connect: system provided
Network: local HTTP server on port 8787, accessed over Tailscale
Checklist