Document Android push-notification troubleshooting for Mattermost

Covers the migrated-from-PikaPods case: stale device registrations
carried over by the DB import, server-to-push-proxy connectivity,
OEM battery optimization, and the push-content setting — the likely
causes when only some Android users stop getting background pushes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AddPmva5bfrUW3MoPriq21
This commit is contained in:
Claude
2026-08-25 22:56:58 +00:00
parent 74b5a0dc7a
commit fce2e7caf1
+81
View File
@@ -0,0 +1,81 @@
## Android push notifications inconsistent after a migration (e.g. from PikaPods)
Symptom: "Enable Push Notifications" is on in System Console, but only some
Android users actually get background push notifications — one user gets
them reliably, others on the same server don't. Since this is per-device
rather than server-wide, work through these in order; the first that
reproduces the symptom is almost always the actual cause.
### 1. Rule out server → push-proxy connectivity first (quick, and if this is
broken it explains ALL users failing, not just some)
The mobile app talks to Google's FCM directly for the device token, but it's
*your* Mattermost server that calls out to the push relay (default
`https://push.mattermost.com`, System Console → Environment → Push
Notification Server) every time it needs to fan out a push. Confirm the new
VPS can actually reach it — a fresh box's outbound rules, or a NAT/firewall
inherited from the migration, can block this silently:
```bash
docker exec mattermost curl -Is https://push.mattermost.com | head -1
```
Then check the server's own logs for push attempts/failures:
```bash
docker compose logs mattermost | grep -i push
```
If specific users' pushes error out while others succeed, that already rules
out a global connectivity/config problem and points at something per-account
(section 2) or per-device (section 3).
### 2. Stale device registration carried over by the migration
A SQL dump import (`migrate-from-pikapods.sh` or any other DB restore) brings
the `Sessions` table with it — including each user's `DeviceId`, the
FCM token that was registered against the *old* server. That registration
only gets refreshed on a real login, not by the app quietly staying open:
a session that survived the move keeps working perfectly for live chat
(the websocket connection has nothing to do with push registration) while
its background push silently stops working, because the token behind it may
now be stale.
This matches "one user is always fine, everyone else isn't" almost exactly —
the working user is typically the one who happened to log out/in (or
reinstalled the app) since the migration, refreshing their `DeviceId`, while
everyone else's session rode through the import unchanged.
**Fix:** have affected users fully log out of the Mattermost Android app
(not just background it — Menu → Log Out) and log back in. This forces a
fresh device-token registration against the current server.
### 3. Android OEM battery optimization (the most common purely-device-side cause)
Xiaomi/MIUI, Huawei, Samsung, OnePlus, and Oppo/Vivo all ship aggressive
battery managers that kill background apps and their FCM listeners by
default — independent of anything about the server. This is the single most
common reason some Android phones on the exact same server get pushes and
others don't, migration or no migration. Have affected users check, per
device:
- **Settings → Apps → Mattermost → Battery** → set to "Unrestricted" / "No
restrictions" / disable "Battery Saver" for the app (menu wording varies
by OEM/Android version).
- **Notification permission itself** is still granted — Android 13+ requires
an explicit runtime permission that can get silently revoked (e.g. after
an OS update), separate from the app's own in-app notification settings.
- Some OEMs (Xiaomi especially) also gate this behind a separate
"Autostart" toggle for the app.
### 4. Push notification content setting, if section 1 and 2 don't explain it
System Console → Environment → Push Notification Server → **Push
Notification Contents**. If set to anything other than "Send full message
contents", the client has to phone the server's own `SiteURL` back for the
real content after getting the push shell — so if the *new* domain isn't
reliably reachable from a given user's network (split-horizon DNS, a mobile
carrier blocking something, a half-finished Caddy/DNS cutover for the new
VPS), that user can receive the push notification itself but never see
real content, or see it inconsistently. Temporarily switching to "Send full
message contents" removes this variable while narrowing down the cause.