[Bug]: App does not load after transferring to a new iOS device if over the air updates are installed

Open Beginner friendly
#8,336 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
68/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
swift
Domain
mobile-dev

Research direction

Start in ios/Capacitor/Capacitor/CAPBridgeViewController.swift and compare the iOS startup path with the Android check referenced in the issue. Use the linked reproduction project to transfer an app with an over-the-air update to another iPhone, then verify that the app opens when the persisted snapshot directory is missing.

Written by the indexing model from the issue text.

Description

platform: ios
Capacitor Version

💊 Capacitor Doctor 💊

Latest Dependencies:

@capacitor/cli: 8.0.2
@capacitor/core: 8.0.2
@capacitor/android: 8.0.2
@capacitor/ios: 8.0.2

Installed Dependencies:

@capacitor/cli: 7.4.2
@capacitor/core: 7.4.2
@capacitor/ios: 7.4.2
@capacitor/android: 7.4.2

Other API Details

Platforms Affected
  • iOS
  • Android
  • Web
Current Behavior

I reproduced this issue using 2 iPhones.

  1. On the first iPhone, install your app with over the air update support.
  2. Open the app and install an over the air update.
  3. Factory reset the other iPhone. Set up this iPhone by transferring all apps and data from the first one.
  4. Open your app. The app immediately closes.

I reproduced this issue with a debug build of the app to get more info. The steps are really similar.

  1. On the first iPhone, install a development build of the app.
  2. Install an over the air update.
  3. Factory reset the other iPhone. During phone setup choose to transfer apps and data from the first phone. Your app isn't installed yet because it's a development build.
  4. Enable developer mode on the second iPhone.
  5. Install your development build of the app on this iPhone. It should use the settings and data transferred from the first phone. When the app opens, it'll immediately close.

I see the following in the Xcode debug console

⚡️  ERROR: Unable to load /var/mobile/Containers/Data/Application/6AE4ECD1-1214-4E0D-B66A-D668CD4C2EAC/Library/NoCloud/ionic_built_snapshots/release:824ca27
⚡️  This file is the root of your web app and must exist before
⚡️  Capacitor can run. Ensure you've run capacitor copy at least
⚡️  or, if embedding, that this directory exists as a resource directory.
Expected Behavior

The app opens successfully.

Project Reproduction

https://github.com/achien/capacitor-server-url-reproduction, relevant code is in capacitor-welcome.js

Additional Information

I debugged the issue and I have a patch that fixes the issue for me. The root cause is the app is trying to load from a directory that does not exist using the persisted serverBasePath in the key value store. The directory is <library>/NoCloud/ionic_built_snapshots/<update> which is not transferred from one phone to the other.

This issue does not happen on Android because it checks that the server path exists before using it, here. I was able to fix the issue on iOS by doing the same check.

diff --git a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
index a7285213..bd8fbaa4 100644
--- a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
+++ b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
@@ -93,10 +93,14 @@ import Cordova
         if !isNewBinary && !descriptor.cordovaDeployDisabled {
             if let persistedPath = KeyValueStore.standard["serverBasePath", as: String.self], !persistedPath.isEmpty {
                 if let libPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {
-                    descriptor.appLocation = URL(fileURLWithPath: libPath, isDirectory: true)
+                    let appLocation = URL(fileURLWithPath: libPath, isDirectory: true)
                         .appendingPathComponent("NoCloud")
                         .appendingPathComponent("ionic_built_snapshots")
                         .appendingPathComponent(URL(fileURLWithPath: persistedPath, isDirectory: true).lastPathComponent)
+
+                    if FileManager.default.fileExists(atPath: appLocation.path) {
+                        descriptor.appLocation = appLocation
+                    }
                 }
             }
         }
Dominant language
TypeScript
Stars
16.7k
Forks
1.3k
Avg merge
3d 10h
Merged PRs (30d)
10

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ionic-team/capacitor

All issues in ionic-team/capacitor

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.