Project Administration

Common Past Issues & Solutions

Developer troubleshooting logs and resolutions for recurring development issues.

⚠️ TODO: MAINTAINED BY AUTHOR
This troubleshooting log is curated and maintained by the lead app authors. Developers should add new entries here when fixing non-obvious integration bugs or platform-specific glitches.

1. Bluetooth & Handshake Issues

GATT 512-Byte Payload MTU Caps

Pairing payloads that exceed the negotiated attribute write/notify limit will result in silent connection drops or transfer exceptions.

Solution & Metrics: BLE GATT transactions are strictly capped at 512 bytes.
  • 1-on-1 Pairings: Currently consume 350-400 bytes (64B public key, 64B user ID, device names, and base64 avatars).
  • Group Joining: Currently consume 380-450 bytes (contains group ID, host key, group name, slot indexes, and encrypted group seeds).
Do not expand JSON structures or username margins without introducing payload compression or GATT fragmentation, as they are within 60-130 bytes of the hard limit.

2. Performance & UI Animations

Lagging UI & Theme Animations

Frame rate stuttering, thread blocking, or frame drops occur when initiating complex animated views (such as pairing, discovery, nuke sequences, or custom loaders).

Solution & Reference: Preload all animation assets (Lottie, custom vectors, or physics assets) during the application startup boot lifecycle or context initialization, ensuring they are cached in RAM before the view renders.

PIN Unlock Reference: Developers should refer to the PIN unlock screen animation implementation as a model. Its assets are preloaded on application startup, preventing frame-drop lag during lock screen transitions. Follow this pattern for all theme animations and future animated elements.

3. Android Platform & Release Builds

Networking Works in Debug but Fails in Release APK

Release builds throw socket error errno 7 when attempting to connect to the relay server, while debug builds work fine.

Solution: Flutter automatically adds the android.permission.INTERNET permission to debug/profile manifests. It must be manually added to the main production manifest (android/app/src/main/AndroidManifest.xml), otherwise network sockets are blocked in release packages.

Release APK Crashes on Launch (Debug is Stable)

Opening the release build triggers immediate crashes with stripping errors like NoSuchMethodException (specifically for WorkDatabase_Impl or platform channels).

Solution: R8 code shrinking strips reflectively-loaded classes. R8 minification is currently disabled. If re-enabled, developers must configure explicit ProGuard keep rules (e.g. for androidx.work and SQLite Room implementations) to prevent bytecode stripping.

4. Signatures & Reinstalls

Testers Can't Install Updates ("Must Uninstall First")

Testers encounter signature mismatch errors when sideloading or installing new build updates.

Solution: The app is debug-signed, meaning signatures differ per development machine. Building on a different machine or changing sign keys changes the signature. Establish a permanent release keystore early to prevent forcing testers to wipe local data.

App "Loses Everything" After Reinstall

Uninstalling and reinstalling the app deletes all active chats, profiles, and contacts, forcing users to re-pair.

Solution: Identity keys and One-Time Pad keystreams are stored locally-only per-install. Wiping or uninstalling the app permanently destroys this vault. Always warn testers before pushing builds that trigger reinstallation.

5. Relay Connection & Verification

“REAUTHENTICATING — PLEASE WAIT…” Banner

A slim banner appears while the app re-issues its device token (the relay forgot the old one — e.g. after a server-side wipe, or a relay update that resets the token store).

Behavior: this is by design, not a hang. The client re-runs the identity gate (proof-of-work, plus the human-verification puzzle when the relay demands one) and reconnects automatically. First-ever connections show the full “Securing your connection” screen instead of the banner. If the user answers the puzzle wrong repeatedly, the relay arms a cooldown (3 wrong answers per hour → 30 minutes) and the app backs off quietly — don't “fix” this by removing the backoff, it exists so clients don't hammer a gate that will refuse them.

Messages Only Arrive After an App Restart

A device stays “connected” (can send) but receives nothing live; everything lands at once after restarting the app.

Root cause (fixed 2026-09, keep it fixed): the relay's connection registry evicted a live connection when an older, dying connection with the same user id unregistered after it — the relay then queued everything for that user as “offline”. The fix is the pointer-identity check in Hub.Run's unregister case (h.clients[id] == client) plus the client's refusal to dial a second socket while already connected to the same relay. If this symptom ever reappears, check both guards first — reverting either reintroduces the race.

“Relay does not support WebSocket stories” Spam

The stories feed error appeared when a refresh ran while the app wasn't authenticated yet.

Solution: feed refreshes skip quietly while offline and re-run when authentication completes. If the error still surfaces for users, their relay genuinely predates the stories capability (or the connection is failing repeatedly) — check the relay version first, not the client.