Repository navigation
[Bug]: iOS backup restore reports success but loses profile and payment history #1733
Description
What happened?
Restoring an iOS-created wallet backup on Android reported WALLET RESTORED, and the Lightning balance returned correctly (499,498 sats), but the saved Pubky profile and payment-request history did not return.
The source iOS wallet had the profile Restore iOS and two Paykit payment-request records, including a manually paid 3,000-sat request marked Proof submitted. After restoration, Android showed Your Name, No payment history, and the profile creation flow instead of the existing profile.
Android logged failures decoding METADATA, SETTINGS, BLOCKTANK and ACTIVITY, then logged Full restore success. Ordinary Lightning transactions were visible, but without their restored contact labels. This report does not claim loss of the Bitcoin balance or a duplicate payment.
Expected behavior
A supported cross-platform backup restores the profile, contacts/payment-request history and compatible wallet data alongside the balance. If a category cannot be restored, show that restoration is incomplete and identify the failed data instead of displaying unconditional success.
Steps to Reproduce
- On iOS, create a regtest wallet and Pubky profile. Link it to a separate contact wallet and fund a Lightning channel.
- Exchange payment requests/payments so the iOS wallet has history. In this run it received 2,500 sats and manually paid a 3,000-sat request, with 499,498 sats remaining.
- Wait for the iOS data backups to complete. Record the recovery phrase privately.
- Reset the source iOS wallet before restoring elsewhere; do not leave the same wallet or Pubky identity active on two installations.
- On a cleared Android installation, restore that iOS wallet from its recovery phrase and finish onboarding.
- Inspect the balance, Profile, and Subscriptions → Payments. Compare with the source profile/history and the Android restore logs.
Control: restoring the same iOS backup on iOS had retained the balance and paid request before the cross-platform attempt. Android-to-Android allowance restoration also passed separately.
Logs / Screenshots / Recordings
The scoped Android log contains:
10-30 09:17:35.362 1267 3113 D APP : 2026-10-30 08:17:35.362 DEBUG [BackupRepo.kt:863] Full restore starting - BackupRepo
10-30 09:17:35.677 1267 1305 W APP : 2026-10-30 08:17:35.676 WARN [BackupRepo.kt:1243] Failed to restore: 'METADATA' [MissingFieldException='Fields [txId, channelId] are required for type with serial name 'com.synonym.bitkitcore.PreActivityMetadata', but they were missing at path: $.tagMetadata[0]'] - BackupRepo
10-30 09:17:35.721 1267 1305 W APP : 2026-10-30 08:17:35.721 WARN [BackupRepo.kt:1243] Failed to restore: 'SETTINGS' [JsonDecodingException='Unexpected JSON token at offset 170: Expected start of the array '[', but had '"' instead at path: $.settings.addressTypesToMonitor
10-30 09:17:37.431 1267 3292 W APP : 2026-10-30 08:17:37.430 WARN [BackupRepo.kt:1243] Failed to restore: 'BLOCKTANK' [JsonDecodingException='Unexpected JSON token at offset 631: Expected beginning of the string, but got { at path: $.info.onchain.network
10-30 09:17:37.480 1267 1295 W APP : 2026-10-30 08:17:37.480 WARN [BackupRepo.kt:1243] Failed to restore: 'ACTIVITY' [JsonDecodingException='Class discriminator was missing and no default serializers were registered in the polymorphic scope of 'Activity'.
10-30 09:17:37.481 1267 1295 I APP : 2026-10-30 08:17:37.481 INFO [BackupRepo.kt:923] Full restore success - BackupRepo
Accessibility snapshots captured before/after restore confirm:
- iOS before restore: payment-request rows for 3,000 sats sent and 2,500 sats received; the sent request has
Proof submittedand noteQA1164. - Android after restore:
NO PAYMENT HISTORY; Profile opensPORTABLE PROFILE, then offersNEW PUBKY/Create profile with Bitkit.
Android offers profile onboarding after restoring the source wallet that already had a profile:
The exact scoped log is included above; source/destination accessibility observations are summarized above. No recording was captured. The full local snapshots remain available for follow-up.
Bitkit Version
- Android destination: 3.0.1 (195), fix: keep allowance history across a wallet restore #1708 at
0f06291d0a4c9cd78c293e199f7797bca5c6b4e7; CI run 40850282647, artifact 12885844952. - iOS source: 3.0.1 (202), fix: keep restored manual payments held bitkit-ios#1164 at
54316decf6a412fb048d2a318800fba05b5fbb98; CI run 40850310428, artifact 12888170145.
Both CI artifact merge trees were verified identical to the respective PR head trees.
Device / OS
- Destination: existing Pixel_6 Android emulator, Android 13.
- Source: existing iPhone 17 simulator, iOS 26.0.
Reproducibility
Observed once in one iOS → Android restore attempt. No repeat-rate claim; not yet reproduced on Android master or a released build.
Additional context
- Backend: local Docker regtest, Electrum, LND and Pubky 0.14.0; local Homegate adapter for signup; CI-default staging VSS/auth for actual backups. Separate wallets and Pubky identities were used for payments, and the source installation was reset before moving its wallet.
- The failure occurs on the Android reader. Whether the shared-format correction belongs in the iOS writer, Android reader, or both still needs investigation.
- At the tested Android head,
BackupRepo.restoreMetadataBackupdecodes the fullMetadataBackupV1before callingpubkyRepo.restoreSessionBackupState. The missing-field exception occurs before the profile restore call. This method is unchanged from fix: keep allowance history across a wallet restore #1708's base,a56c75be32ed727ac71f16fd5b837cc3cff80c46; that alone does not prove when the bug was introduced. See the pinned restore path. - The allowance-specific WALLET restore logged success; the missing profile prevented validating the iOS-origin request/allowance UI. This is not established as an allowance wire-format defect or a regression introduced by fix: keep allowance history across a wallet restore #1708 or iOS fix: consume vss-client 0.5.23 #1164. Track it separately and link it from fix: keep allowance history across a wallet restore #1708's device results.
- Related historical work: Hardware Wallet Data Backup & Restore #1046 (closed), which covers Core-owned backup field migration. This report concerns the observed iOS-produced payload failures and misleading restore-success result, not just missing
walletIdmigration.
Acceptance: repeat iOS → Android restoration with profile, contact metadata, automatic and manual payment history; verify all expected data and balances survive. Add fixture coverage for the reported field/type mismatches and verify category failures cannot produce an unconditional success result.
Activity
ovitrif commentedon Oct 30, 2026
Triage: 3.2.0. The iOS-to-Android restore gap reproduces on 3.0.1 builds, so it is not a 3.1.0 regression, and no PR fixes it yet; 3.1.0 is down to its cut-line PRs (https://synonymworkspace.slack.com/archives/C07BJ7DNPCG/p1793307568629859). It can move into 3.1.0 if a fix lands before the RC.
ovitrif commentedon Oct 30, 2026
Moving this issue to 3.1.0: a fix is in progress for it, and the 3.1.0 cut now takes fixes merged over the weekend, before the RC on Monday 2 Nov.
ovitrif commentedon Nov 2, 2026
Fixed by #1736.