Repository navigation
Open
Labels
bugSomething isn't workingSomething isn't working
Description
NOOP version
9.0.1-staging
Platform
Android
OS version
16
WHOOP strap model
WHOOP 4.0
Where the data is coming from
Live Bluetooth (strap connected)
Test Centre profile
HRV & Autonomic
What happens
Even though live heart rate in Noop and Whoop is equal, the RHR in Noop is about 5 bpm lower (compared to Whoop and Polar H10).
HRV (activated deep sleep window doesn't change anything) is too high in Noop (49) vs Whoop and Polar (both 30).
Something seems to be wrong with the calculation.
noop-strap-log-260717-0949.txt
What you expected instead
There should be equal data to calculate effort, rest and strain in the correct way.
Steps to reproduce
Strap log
<details><summary>Strap log (last 40 lines, redacted)</summary>
09:39:13 [display] frameSummary frames=60 mean=19.6ms p95=16.6ms hitches=2 worst=149.1ms threshold=33.0ms
09:39:14 [display] frameSummary frames=60 mean=19.3ms p95=16.6ms hitches=2 worst=99.4ms threshold=33.0ms
09:39:14 Get Data Range raw frame (#451 — for offset analysis): aa1800ff280222dc596a90512f0000000000000000000104a2e54ab4
09:39:14 Strap newest banked record: 2026-07-17 09:39 (from data range)
09:39:14 [universal] clockDrift newest=2026-07-17 07:39:14 wall=2026-07-17 07:39:14 newestVsWall=+0s clockOk
09:39:15 [display] frameSummary frames=60 mean=18.5ms p95=16.6ms hitches=1 worst=132.6ms threshold=33.0ms
09:39:16 [display] frameSummary frames=60 mean=16.0ms p95=33.1ms hitches=3 worst=198.8ms threshold=33.0ms
09:39:17 [display] frameSummary frames=60 mean=12.3ms p95=11.1ms hitches=2 worst=55.3ms threshold=33.0ms
09:39:18 [display] frameSummary frames=60 mean=14.7ms p95=11.1ms hitches=2 worst=121.6ms threshold=33.0ms
09:39:19 [display] frameSummary frames=60 mean=17.7ms p95=18.4ms hitches=1 worst=121.6ms threshold=33.0ms
09:39:20 [display] frameSummary frames=60 mean=20.1ms p95=16.5ms hitches=2 worst=148.9ms threshold=33.0ms
09:39:21 [display] frameSummary frames=60 mean=21.5ms p95=49.6ms hitches=3 worst=165.5ms threshold=33.0ms
09:39:22 [display] frameSummary frames=60 mean=17.1ms p95=16.5ms hitches=1 worst=49.6ms threshold=33.0ms
09:39:24 [display] frameSummary frames=60 mean=21.8ms p95=16.5ms hitches=2 worst=182.0ms threshold=33.0ms
09:39:25 [display] frameSummary frames=60 mean=20.1ms p95=16.5ms hitches=2 worst=132.4ms threshold=33.0ms
09:39:26 [display] frameSummary frames=60 mean=19.9ms p95=16.5ms hitches=2 worst=182.0ms threshold=33.0ms
09:39:27 [display] frameSummary frames=60 mean=21.8ms p95=49.6ms hitches=3 worst=182.0ms threshold=33.0ms
09:39:29 [display] frameSummary frames=60 mean=19.6ms p95=16.5ms hitches=2 worst=115.8ms threshold=33.0ms
09:39:29 [display] frameSummary frames=60 mean=15.0ms p95=19.8ms hitches=2 worst=148.9ms threshold=33.0ms
09:39:30 [display] frameSummary frames=60 mean=12.3ms p95=12.3ms hitches=2 worst=66.3ms threshold=33.0ms
09:39:31 [display] frameSummary frames=60 mean=12.7ms p95=11.1ms hitches=2 worst=66.3ms threshold=33.0ms
09:39:32 [display] frameSummary frames=60 mean=12.0ms p95=11.1ms hitches=1 worst=66.3ms threshold=33.0ms
09:39:33 [display] frameSummary frames=60 mean=17.0ms p95=28.2ms hitches=2 worst=165.8ms threshold=33.0ms
09:39:34 [display] frameSummary frames=60 mean=22.1ms p95=49.8ms hitches=3 worst=165.8ms threshold=33.0ms
09:39:35 [display] frameSummary frames=60 mean=19.6ms p95=16.6ms hitches=2 worst=132.6ms threshold=33.0ms
09:39:36 [display] frameSummary frames=60 mean=19.6ms p95=16.6ms hitches=2 worst=132.6ms threshold=33.0ms
09:39:38 [display] frameSummary frames=60 mean=21.6ms p95=16.6ms hitches=2 worst=182.4ms threshold=33.0ms
=== Capture check ===
universal: present (dayOwner day=)
sleep: present (gate run=)
connection: present (clockDrift )
workouts: MISSING (expected session event=)
display: present (dataVolume dbRows=)
import: MISSING (expected import parser=)
steps: present (stepsEst )
battery: present (battery series=)
recovery: MISSING (expected charge score=)
hrv: present (via hrv nightSummary)
INCOMPLETE: missing workouts, import, recovery
bundle ok files=3 report=present meta=present screenshot=present crash=present leaks=0
</details>
Before you submit
- I attached my exported NOOP .zip (not a screenshot of the Live screen). If my bug is a clearly reproducible UI issue I described exactly how to see it instead.
- I attached or pasted a strap log above — or my bug is a clearly reproducible UI issue that doesn't need one (e.g. a typo, a button that does nothing) and I've described exactly how to see it.
- I checked the Troubleshooting guide — especially "history syncs but no data" (most often the strap isn't banking history to flash; charge it to 100% and reconnect).
- I checked the FAQ and — if I'm on a WHOOP 5.0 / MG — the 5.0/MG status page, and this isn't an already-known limit (e.g. SpO₂, or recovery/sleep on the 5/MG).
- I've left out anything personal (strap serial, account email, raw export).
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
Preview a same-second R-R de-dup in the #257 HRV diag to scope the do…
Preview a same-second R-R de-dup in the #257 HRV diag to scope the do…
Preview a same-second R-R de-dup in the ryanbr#257 HRV diag to scope …
ryanbr commentedon Jul 25, 2026
First real evidence on the HRV half, from @pilleuspulcher-blip's log in #803 (WHOOP 4.0, 9.1.1-staging):
The diagnostic's own rule is that
collapsedCovwell belowcoveragemeans the over-count is same-second and a de-dup fixes it; still high means cross-second overlap. 07-16 only drops 2.54 → 1.99, so it is cross-second — the same-second de-dup previewed here would not be sufficient on this data. 07-15 is clean at 0.89, so it is night-specific rather than constant.Worth noting the two nights produce similar RMSSD (52 vs 48) despite very different coverage, so the relationship between over-count and inflated HRV is not simply linear. More logs would help before committing to a fix shape.
On the RHR half: that reporter's ~7 bpm gap versus the WHOOP app is fully explained by floor-vs-mean (
floor=44 nightMean=50,floor=40 nightMean=48), which is by design. The recurring problem is discoverability — the explanation lives indocs/ANALYTICS.mdand a v7.0.0 release note saying it is "answerable straight from the log", so a user has to export and read a log to learn their RHR is not broken. Surfacing it where RHR is displayed would close most of these reports; noting it here rather than opening a separate issue since this is the master.docs: add an in-repo FAQ and point the issue templates at it (#809)
fix: unmeasurable is its own verdict, and NaN no longer diverges (#550)
perf: compute each coverage figure once, not twice (#550)
diag(hrv): say which R-R over-count a night has, not just the numbers (…
Bump build numbers for a fresh 9.1.1 testing build
Give classifyCoverage a floor, so a night missing beats stops reading…
fix(hrv): stop reporting SDNN for a capture already known to be over-…
fix(hrv): stop reporting SDNN for a capture already known to be over-…
fix(hrv): stop reporting SDNN for a capture already known to be over-…
hrv: sample the densest second on an over-count night (#1008) (#1117)
fixup: reattach collapsedCoverage doc (collapseOverCount was inserted…
diag(hrv): shadow-log a deduped R-R stream to validate the over-count…
Preview a same-second R-R de-dup in the ryanbr#257 HRV diag to scope …
docs: add an in-repo FAQ and point the issue templates at it (ryanbr#809
diag(hrv): say which R-R over-count a night has, not just the numbers (…
Bump build numbers for a fresh 9.1.1 testing build
Give classifyCoverage a floor, so a night missing beats stops reading…
fix(hrv): stop reporting SDNN for a capture already known to be over-…
hrv: sample the densest second on an over-count night (ryanbr#1008) (r…
diag(hrv): shadow-log a deduped R-R stream to validate the over-count…