Two bugs, both live, found while working out why a TestFlight tester
got no message notifications.
The relay retried a token that can never work. Only a 410 dropped
one. A 400 BadDeviceToken — a token minted by a debug build installed
from Xcode, which a production host will refuse forever — stayed in the
table, costing an error line and a wasted round trip on every message
that device should have received, permanently. It is now forgotten,
which costs nothing: the app registers a fresh token on its next
foreground, the same path a reissued token takes.
And the log told the operator to break everyone else's pushes. The
advice was an unconditional "set FN_APNS_ENV=sandbox and restart". That
was written when the relay defaulted to sandbox and the failure mode was
every push failing. On a relay serving real TestFlight users it is the
wrong way round: one developer's phone would have talked an operator
into disabling notifications for every actual user. Observed on
2026-09-08 — two BadDeviceToken errors from one debug install, on a
relay whose production setting was correct and whose other devices were
fine.
The two cases are told apart by whether this relay has ever had a
push accepted. Nothing else can: the response is byte-identical and the
token is opaque. One success proves the host, which makes every later
refusal a fact about that device. Before any success the host is still
the suspect, the old advice stands, and a token is NOT dropped — turning
a one-line configuration fix into re-registering every device would be
the worse failure.
Both paths, ordinary and VoIP. The existing tests defended a hedge and a
stated consequence; both were right and are kept, in the branch where
they are still true.
Two bugs, both live, found while working out why a TestFlight tester
got no message notifications.
**The relay retried a token that can never work.** Only a 410 dropped
one. A 400 BadDeviceToken — a token minted by a debug build installed
from Xcode, which a production host will refuse forever — stayed in the
table, costing an error line and a wasted round trip on every message
that device should have received, permanently. It is now forgotten,
which costs nothing: the app registers a fresh token on its next
foreground, the same path a reissued token takes.
**And the log told the operator to break everyone else's pushes.** The
advice was an unconditional "set FN_APNS_ENV=sandbox and restart". That
was written when the relay defaulted to sandbox and the failure mode was
every push failing. On a relay serving real TestFlight users it is the
wrong way round: one developer's phone would have talked an operator
into disabling notifications for every actual user. Observed on
2026-09-08 — two BadDeviceToken errors from one debug install, on a
relay whose production setting was correct and whose other devices were
fine.
The two cases are told apart by whether this relay has ever had a
push accepted. Nothing else can: the response is byte-identical and the
token is opaque. One success proves the host, which makes every later
refusal a fact about that device. Before any success the host is still
the suspect, the old advice stands, and a token is NOT dropped — turning
a one-line configuration fix into re-registering every device would be
the worse failure.
Both paths, ordinary and VoIP. The existing tests defended a hedge and a
stated consequence; both were right and are kept, in the branch where
they are still true.
3 new tests. 697 tests green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Two bugs, both live, found while working out why a TestFlight tester
got no message notifications.
The relay retried a token that can never work. Only a 410 dropped
one. A 400 BadDeviceToken — a token minted by a debug build installed
from Xcode, which a production host will refuse forever — stayed in the
table, costing an error line and a wasted round trip on every message
that device should have received, permanently. It is now forgotten,
which costs nothing: the app registers a fresh token on its next
foreground, the same path a reissued token takes.
And the log told the operator to break everyone else's pushes. The
advice was an unconditional "set FN_APNS_ENV=sandbox and restart". That
was written when the relay defaulted to sandbox and the failure mode was
every push failing. On a relay serving real TestFlight users it is the
wrong way round: one developer's phone would have talked an operator
into disabling notifications for every actual user. Observed on
2026-09-08 — two BadDeviceToken errors from one debug install, on a
relay whose production setting was correct and whose other devices were
fine.
The two cases are told apart by whether this relay has ever had a
push accepted. Nothing else can: the response is byte-identical and the
token is opaque. One success proves the host, which makes every later
refusal a fact about that device. Before any success the host is still
the suspect, the old advice stands, and a token is NOT dropped — turning
a one-line configuration fix into re-registering every device would be
the worse failure.
Both paths, ordinary and VoIP. The existing tests defended a hedge and a
stated consequence; both were right and are kept, in the branch where
they are still true.
3 new tests. 697 tests green.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
assigned to @paulhitt
restored source branch
fix/a-bad-token-is-not-a-config-problemmentioned in commit
1f63aac807changed the description