Troubleshooting
Long Ping writes every state change, restart, upload result and rejected fix to a log on the device. When a phone “went quiet”, the log usually says why.
Reading the log
Section titled “Reading the log”const text = await LongPing.logger.getLog({ sinceMs: Date.now() - 6 * 60 * 60 * 1000, // last 6 hours (default: last 24 hours) limit: 2000, // newest 2000 entries (default 1000) order: 'desc', // newest first (default 'asc')});One entry per line: timestamp (UTC), level, tag, message.
2026-10-26T07:58:02.114Z INFO [engine] tracking started2026-10-26T07:58:03.870Z INFO [engine] recorded motionchange (moving, ±6 m)2026-10-26T07:58:33.902Z INFO [engine] recorded interval (moving, ±5 m)2026-10-26T07:59:04.011Z INFO [http] POST https://api.example.com/locations -> 200, 2 records, 184 ms2026-10-26T08:41:15.330Z WARN [http] upload failed (network error); next attempt in 11 s2026-10-26T08:44:02.508Z INFO [engine] now parked2026-10-26T09:52:40.001Z WARN [engine] no fix for 312 s; restarting location updateslogLevel(default'info') controls how much is written;'debug'adds skipped fixes, ignored config keys and more. Use it while testing.- Entries are kept for
logMaxDays(default 3, up to 30). logger.clear()deletes the log.
Getting it off a phone
Section titled “Getting it off a phone”Add a “Send diagnostics” action to your app and post the log to your server:
async function sendDiagnostics() { const [log, state, provider] = await Promise.all([ LongPing.logger.getLog({ sinceMs: Date.now() - 24 * 60 * 60 * 1000 }), LongPing.getState(), LongPing.getProviderState(), ]); await fetch('https://api.example.com/diagnostics', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ log, state, provider }), });}getProviderState() alone answers a lot: permission level, precise or reduced accuracy, location services,
power-save mode and (Android) battery-optimization exemption.
Symptoms and causes
Section titled “Symptoms and causes”No fixes at all after start()
Section titled “No fixes at all after start()”start()rejected: check forPERMISSION_DENIEDorLOCATION_SERVICES_OFF.- iOS:
UIBackgroundModes→locationis missing, so tracking stops in the background. The log has an error about it. See Installation. - Android: the device has no Google Play Services (v0.1 uses the fused provider only).
- All fixes are less accurate than
minAccuracyM(indoors, reduced accuracy on iOS). One is still recorded when a fix is overdue by 30 s;logLevel: 'debug'shows the rejected ones.
Hours-long gaps on some Android phones
Section titled “Hours-long gaps on some Android phones”Almost always an OEM battery manager freezing the app. Look for “no fix for … s; restarting location updates” or “service restarted by the system” when it came back. Walk the user through Android battery managers.
Gaps on iPhone after the app was swiped away
Section titled “Gaps on iPhone after the app was swiped away”Expected: iOS stops a swiped-away app until the device moves a few hundred meters, then relaunches it. See
How iOS background tracking works. Set stopOnTerminate: true if you want a
swipe-away to stop tracking instead.
Fixes are recorded but nothing reaches the server
Section titled “Fixes are recorded but nothing reaches the server”Check getState() and the http lines in the log:
| You see | Cause |
|---|---|
No http lines at all |
http.url is null or '' (record-only mode). |
authorizationRequired: true, “uploads paused” |
401/403 and no working refresh. Call setAuthorization(); see Authentication. |
| “upload failed …; next attempt in N s” | Network errors, 408, 429 or 5xx: backoff, up to 15 minutes. sync() retries now. |
Status 0 on every attempt |
No connectivity, DNS, TLS, or (in development) cleartext HTTP blocked by ATS / network security config. |
Records vanished without arriving
Section titled “Records vanished without arriving”- “dropped N records after 3 rejected attempts”: your server answered a 4xx other than 401, 403, 408, 413 or 429 three times. Answer 2xx for batches you can mostly use.
- “queue pruned”: the queue hit
persistence.maxRecordsor records got older thanpersistence.maxDayswhile the device couldn’t upload.
The same record arrives twice
Section titled “The same record arrives twice”Retries after a lost reply resend records. Deduplicate on uuid; see
Receiving uploads.
Never switches to parked, or flips back and forth
Section titled “Never switches to parked, or flips back and forth”- GPS drift where you park is larger than
stopRadiusM(75 m): raise it. - Stops are shorter than
stopTimeoutSec(300 s): lower it, if you want short stops to count. - Walking around with the phone above
movingSpeedMps(3 m/s) counts as moving. disableStopDetection: truenever parks.
Fixes come less often than the interval
Section titled “Fixes come less often than the interval”lowBatteryis set, the phone isn’t charging and the battery is belowbelowPct.- Fixes are being filtered by
minAccuracyMuntil one is overdue. - The device is parked and on
parkedIntervalSec. - A remote config changed the interval (look for “server config applied” /
configchange).
Tracking stopped by itself
Section titled “Tracking stopped by itself”Long Ping never stops on its own. Only stop() or a server reply with {"long_ping": {"stop": true}} stops
tracking (both are logged), or, with stopOnTerminate: true, the app being terminated. Auth failures, network
failures and bad responses only pause or retry uploads.
No notification on Android 13+
Section titled “No notification on Android 13+”Your app hasn’t been granted POST_NOTIFICATIONS. Tracking still runs; the notification is hidden.