← Back to Blog

Move to iOS Won't Transfer WhatsApp. Here's the Fix Android Won't Give You.

March 22, 2026

Three Android phones, one weekend, zero successful WhatsApp transfers. The error is 'Failed to find provider info for com.whatsapp.provider.migrate.ios.' The fix is a shell script. The journey to get there involved ADB forensics, a 2014 APK from the Wayback Machine, and a manual database decryption pipeline I never needed.

Three phones, zero transfers

The weekend's plan was simple: migrate three Android phones to iPhones. Move to iOS handles this. You scan a code, select your data, wait for the progress bar. It works.

Except for WhatsApp. On all three phones, toggling the WhatsApp switch in Move to iOS errored out immediately. No progress bar. No useful message. Three different Android devices, three identical failures.

The logcat told a clearer story:

E ActivityThread: Failed to find provider info for com.whatsapp.provider.migrate.ios
V whatsapp: did receive a null cursor from files.

Move to iOS was looking for a ContentProvider that WhatsApp is supposed to expose for migration. It couldn't find it. Not because the provider doesn't exist — it does, right there in WhatsApp's manifest — but because Android wasn't letting anyone see it.

Three layers of "no"

Digging through adb shell dumpsys package com.whatsapp revealed three distinct protection mechanisms stacked on top of each other:

Package visibility. Android 11 introduced restrictions where apps can't see each other's components unless explicitly declared. WhatsApp's manifest declares visibility to com.google.android.apps.pixelmigrate and com.google.android.apps.restore — Google's own migration tools. Apple's com.apple.movetoios? Not on the list. The system blocks Move to iOS from seeing WhatsApp's provider entirely.

Disabled component. The migration provider (ExportMigrationContentProvider) isn't in WhatsApp's enabledComponents list. It appears to activate only when WhatsApp itself initiates the migration flow — which it can't do if Move to iOS can't see it in the first place.

Signature-level permission. com.whatsapp.permission.MIGRATION_CONTENT_PROVIDER is prot=signature. Only apps signed by Meta can access it directly.

Three layers of protection, each independently sufficient to block the transfer. And none of this surfaces to the user. You get a spinner that immediately fails.

The wrong road (which I walked to the end)

Before finding the simple fix, I went deep into the manual migration path. Not out of necessity — out of stubbornness and the sunk cost of already having ADB connected.

The plan: decrypt the Android WhatsApp database, convert it to iOS format, inject it into an iPhone backup. Open source tools exist for each step. In theory.

Step 1: Extract the encrypted database. WhatsApp stores messages in msgstore.db.crypt14, a SQLite database encrypted with a key that lives in the app's private storage. Pulling the encrypted file is easy. Getting the key is not.

Step 2: The legacy APK trick. Modern WhatsApp blocks adb backup. But WhatsApp v2.11.431 — from 2014 — doesn't. The technique: back up the current APK, uninstall WhatsApp while keeping data (pm uninstall -k), install the 2014 version from the Wayback Machine1, run adb backup, extract the encryption key from the backup archive, reinstall the current version.

# The Wayback Machine URL for a 2014 WhatsApp APK. This is real.
curl -L -o /tmp/LegacyWhatsApp.apk \
  "https://web.archive.org/web/20141111030303if_/http://www.whatsapp.com/android/current/WhatsApp.apk"

It worked. 158-byte key extracted. Database decrypted. 4,229 messages across 866 chats.

Step 3: The schema surprise. WhatsApp's database schema changed sometime in 2024. The messages table is now message. JIDs use an internal @lid format mapped through a jid table. Every open source tool that converts WhatsApp Android databases to iOS format expects the old schema.

I wrote compatibility SQL views — legacy_available_messages_view, group_participants, an updated chat_view — to map the new schema back to the old column names. 4,224 messages across 96 visible chats, ready for conversion.

Step 4: The wall. The iOS side requires WhatsApp's CoreData model files (.momd) to build the destination database. These files live inside the WhatsApp iOS app binary. Extracting them requires either a jailbroken iPhone or a decrypted IPA. I had neither. The conversion pipeline stalled.

The fix I should have tried first

Here's the thing: during the legacy APK trick in Step 2, I'd already done an uninstall-reinstall cycle. And I'd done it specifically because the fresh install re-registers components with Android's PackageManager.

The same mechanism that enabled adb backup on the legacy APK also re-enables the migration ContentProvider on the current one. A fresh install from a direct APK download — bypassing Play Store — forces the PackageManager to re-scan all components from the manifest. The provider that Play Store updates had left in a stale disabled state gets re-registered as enabled.

The minimal fix:

# Back up current APK on device
APK_PATH=$(adb shell pm path com.whatsapp | head -1 | sed 's/package://')
adb shell cp "$APK_PATH" /data/local/tmp/WhatsAppbackup.apk

# Uninstall keeping all data (-k preserves messages, media, settings)
adb shell pm uninstall -k com.whatsapp

# Download and install fresh from whatsapp.com (NOT Play Store)
curl -L -o /tmp/WhatsApp.apk "https://www.whatsapp.com/android/current/WhatsApp.apk"
adb install -r -d -g /tmp/WhatsApp.apk

That's it. Messages preserved. Media preserved. Settings preserved. The -k flag keeps all app data during uninstall. The fresh install from a direct APK forces component re-registration. Move to iOS can now see the provider.

Tested on a Pixel 3 XL (Android 12) and a CMF by Nothing A001 (Android 15). Both fixed.

The script

I packaged this into a single script — fix.sh — that handles device detection, APK backup, the uninstall-reinstall cycle, and automatic rollback if anything fails. It's on GitHub.

git clone https://github.com/digital-rain-tech/whatsapp-move-to-ios-fix.git
cd whatsapp-move-to-ios-fix
./fix.sh

The whole fix takes about two minutes. I spent a weekend to find it.

If you use Claude Code, there's also a skill that walks you through the diagnosis and fix interactively:

# Install the skill
mkdir -p ~/.claude/skills/fix-move-to-ios-whatsapp
curl -o ~/.claude/skills/fix-move-to-ios-whatsapp/SKILL.md \
  https://raw.githubusercontent.com/digital-rain-tech/whatsapp-move-to-ios-fix/main/skills/fix-move-to-ios-whatsapp/SKILL.md

# Then in Claude Code, just describe the problem or run:
/fix-move-to-ios-whatsapp

It handles device detection, runs the ADB commands, and escalates through the fix attempts automatically.

What I learned

The manual migration pipeline — the encryption key extraction, the database decryption, the schema compatibility views — was unnecessary. Every hour I spent on it was an hour I could have spent verifying that the simple reinstall worked. I went deep because the problem looked deep. Three layers of Android protection. Signature-level permissions. Surely the fix requires matching sophistication.

It didn't. Play Store updates leave a component in a stale state. A fresh install resets it. The complexity was in the diagnosis, not the solution.

The other thing: this bug affects everyone migrating from Android 11+ to iPhone with WhatsApp data. Millions of people. The error message gives you nothing. The official guidance is "make sure both apps are updated" — which doesn't help when the update mechanism is the problem. Somewhere in the gap between Google's package visibility restrictions and Meta's provider registration, there's a class of user who will lose their WhatsApp history because neither company's support documentation acknowledges the interaction.

A shell script shouldn't be the answer. But today, it is.

Footnotes

  1. The Wayback Machine hosts WhatsApp v2.11.431, released in 2014. MD5: 73fa47a3870d0b9ee6e29d843118e09b. This version predates Android's adb backup restrictions, making it useful for key extraction. Don't leave it installed — it's twelve years old.