Skip to content

5/MG: the backfill deferral reads as hopeless while the unbonded-offload probe sits unmentioned behind a Test Centre toggle #1802

Open

Description

@ryanbr

The problem

On a WHOOP 5/MG that cannot bond, the backfill diagnostic explains the dead end accurately and then
stops, without naming the one action that exists:

Backfill: deferred — connect handshake not done yet (family=WHOOP5 didBond=false
helloWrittenThisLink=false bondRequestedThisLink=false deferrals=2 sinceConnect=8812s). No hello was
written on this link, so didBond cannot become true and this gate cannot open for the rest of it.
SET_CLOCK rides the same handshake tail, and an un-clocked 5/MG is hardware-known not to persist
sensor data to flash (#78 fork) — so there may also be nothing banked to offload.

Every clause is true. Read by a user, it says the situation is hopeless. It is not: NOOP ships
shouldProbeUnbondedOffload, designed for precisely this strap in precisely this state, and its
stage 3 is SET_CLOCK — the thing the line above says never runs.

What the field report showed

11.0.0-staging, 5/MG on fw 50.41.1.0, 7,861 log lines. The probe had never run — no puffin
subscribe, no GET_CLOCK, no authentication refusal anywhere. optedIn is false, and the toggle
lives in Test Centre ("Try history sync without pairing (experimental)"), which is not somewhere a
user lands from "Rest says No data".

The install had gone weeks in the state the probe was written to answer, while the strap sat in
exactly the condition it requires — note helloWrittenThisLink=false is a precondition of the
probe, not an obstacle to it.

Consequence: no motion, no steps, no workouts, no Rest, and no route to the one measurement that
would settle whether any of it is recoverable.

Why it matters beyond one user

The probe's docstring is explicit that this is the last open question on #1635:

A refusal is a RESULT. Either outcome closes the last open question on #1635.

Nobody can supply that result while the only path to it is an experimental toggle on a screen users
reach for other reasons. The two outcomes lead to completely different roadmaps — a refusal makes
#1801's HR-only fallback the only route to Rest on this hardware; a pass means motion, steps and
sleep all return once the strap is clocked.

Shape

When the deferral repeats on a 5/MG with didBond=false and the probe is available but not opted
in, say so at the point of failure — in the diagnostic line, and ideally where the user actually
sees the symptom. It stays opt-in and self-limiting (once per link, latches on refusal, retires
after N silent links); this is about discoverability, not about running it automatically.

Related: #1801 (the fallback that matters if the probe is refused).

Activity

  1. ryanbr commented on Sep 2, 2026

    @ryanbr
    OwnerAuthor

    The probe has now been run on a real 5/MG in the exact state it was written for, and the result must
    not be recorded as the answer this issue was waiting on. Full analysis in #1804.

    Short version: it made three attempts, concluded the strap refuses the offload unbonded, and retired
    itself — but all three links were terminated locally, not by the strap.

    [connection] reconnect n=2 reason=localTerminate via=unknown
    Disconnected (status=22)          # GATT_CONN_TERMINATE_LOCAL_HOST
    

    The same strap, in the same log, holds links for 7559.7 s, 2936.3 s and 458.8 s. The three probe
    attempts ended at 10776 / 10761 / 10787 ms — a 30 ms spread, which is a timer rather than a radio
    event. No ATT errors and no writeDescriptor busy errors anywhere in the log; the four subscribes
    just never called back in the ~3 s before the local hang-up.

    Stage 1 never completed, so GET_CLOCK and SET_CLOCK never ran. The open question is still open.

    Two things this changes for this issue:

    1. Discoverability is no longer the only blocker. Pointing more users at the toggle would now
      collect false negatives at scale and latch them per-device, which is worse than not asking. 5/MG unbonded-offload probe reads its own local teardown as a strap refusal, and latches on it #1804
      should land first.
    2. The per-link message asserts the strap is at fault by analogy to CLIENT_HELLO's signature. That
      analogy does not hold on a link with no hello and no SMP in flight — the docstring attributes the
      hello teardown to the bond watchdog, which cannot be running here. Whatever surfacing this issue
      adds should not repeat that claim.

    The user-facing part of this issue stands and is arguably sharper now: someone in this state gets a
    diagnostic that reads as settled ("offload is not reachable on this strap without a bond") when
    nothing has actually been measured.

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

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions