title: How can I diagnose and resolve a crash on WCSession sendMessage(_:replyHandler:errorHandler:)?
body: <p>I'm building a watchOS app that needs to periodically request information from a companion iPhone app to refresh a complication.</p>
  
  <p>To achieve this, I have a <code>WKApplicationRefreshBackgroundTask</code> that runs periodically. It uses <code>sendMessage(_:replyHandler:errorHandler:)</code> from <code>WatchConnectivity</code> to request the information from the iPhone app, process the reply, and update the complication.</p>
  
  <p>This works reliably for many users most of the time, however, I’m seeing Apple Watch crashes in Xcode related to <code>sendMessage(_:replyHandler:errorHandler:)</code> and I worry this is leading to missed complication updates for users. Some users have been complaining about the complication not updating, so I'm trying to identify if there are issues outside of the regular limitations on how often a complication can refresh in watchOS.</p>
  
  <p><strong>Does anyone have any suggestions on how I can fix this issue?</strong> Or, do you have any suggestions for how I can better troubleshoot what's going wrong to cause the crash and figure out how to prevent it?</p>
  
  <p>I've included a full example of one of the crashes at the bottom, along with the code that handles the background task and the code that handles sending and receiving values from the paired iPhone.</p>
  
  <p>I’m never sending a message without a replyHandler, so while <a href="https://stackoverflow.com/questions/33200630/wcsession-sendmessagereplyhandler-error-code-7014-wcerrorcodedeliveryfailed">others have seen problems because the delegate method for a message without a handler was not implemented</a> on iPhone, I don’t think that’s the issue here. To be safe I implemented the delegate method on iPhone as an empty method that does nothing.</p>
  
  <p><strong>UPDATE 30 January 2020:</strong> A friend suggested that maybe the issue is that the task is being marked complete by the 10 second timer while it's still in progress, causing a memory issue when something that's pending finishes, but wasn't sure what could be done about it. Maybe that's core to the issue here?</p>
  
  <p>Here's my background refresh code from <code>ExtensionDelegate</code>:</p>
  
  <pre><code>func handle(_ backgroundTasks: Set&lt;WKRefreshBackgroundTask&gt;) {
      for task in backgroundTasks {
          switch task {
          case let backgroundTask as WKApplicationRefreshBackgroundTask:
  
              // set a timer in case it doesn't complete
              // the maximum allowed is 15 seconds, and then it crashes, so schedule the new task and mark complete after 10
              var timeoutTimer: Timer? = Timer.scheduledTimer(withTimeInterval: 10, repeats: false) { (timer) in
  
                  self.scheduleBackgroundRefresh()
  
                  backgroundTask.setTaskCompletedWithSnapshot(false)
              }
  
              // schedule the next refresh now in case the request crashes
              scheduleBackgroundRefresh()
  
              WatchConnectivityManager.shared.requestDataFromPhone()
  
              ComplicationManager.shared.reloadComplication()
  
              // as long as the expiration timer is valid, cancel the timer and set the task complete
              // otherwise, we'll assume the timer has fired and the task has been marked complete already
              // if it's marked complete again, that's a crash
              if let timerValid = timeoutTimer?.isValid, timerValid == true {
                  timeoutTimer?.invalidate()
                  timeoutTimer = nil
                  backgroundTask.setTaskCompletedWithSnapshot(true)
              }
  
          default:
              // make sure to complete unhandled task types
              task.setTaskCompletedWithSnapshot(false)
          }
      }
  }
  
  private func scheduleBackgroundRefresh() {
  
      let fiveMinutesFromNow: Date = Date(timeIntervalSinceNow: 5 * 60)
  
      WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fiveMinutesFromNow,
      userInfo: nil) { (error) in
          if let error = error {
              fatalError("\(error)")
          }
      }
  }
  </code></pre>
  
  <p>And here is <code>WatchConnectivityManager</code>:</p>
  
  <pre><code>import Foundation
  import WatchKit
  import WatchConnectivity
  
  class WatchConnectivityManager: NSObject {
  
      static let shared = WatchConnectivityManager()
  
      let session = WCSession.default
  
      private let receivedMessageQueue: OperationQueue = {
          let queue = OperationQueue()
          queue.maxConcurrentOperationCount = 1
          return queue
      }()
  
      private func process(messageOrUserInfo: [String : Any]) {
  
          receivedMessageQueue.addOperation {
              if let recievedValue = messageOrUserInfo["ValueFromPhone"] as? Int {
                  DispatchQueue.main.async {
                      ViewModel.shared.valueFromPhone = recievedValue
                  }
              }
          }
      }
  
      func requestDataFromPhone() {
  
          if session.activationState == .activated {
  
              let message: [String : Any] = ["Request" : true]
  
              let replyHandler: (([String : Any]) -&gt; Void) = { reply in
  
                  self.process(messageOrUserInfo: reply)
              }
  
              let errorHandler: ((Error) -&gt; Void) = { error in
              }
  
              if session.isReachable {
                  session.sendMessage(message,
                                      replyHandler: replyHandler,
                                      errorHandler: errorHandler)
              }
  
              // send a request to the iPhone as a UserInfo in case the message fails
              session.transferUserInfo(message)
          }
      }
  }
  
  extension WatchConnectivityManager: WCSessionDelegate {
  
      func session(_ session: WCSession,
                   activationDidCompleteWith activationState: WCSessionActivationState,
                   error: Error?) {
  
          if activationState == .activated {
              requestDataFromPhone()
          }
      }
  
      func session(_ session: WCSession,
                   didReceiveUserInfo userInfo: [String : Any])
      {
          process(messageOrUserInfo: userInfo)
      }
  }
  </code></pre>
  
  <p>Example crash:</p>
  
  <pre><code>Hardware Model:      Watch3,4
  AppVariant:          1:Watch3,4:6
  Code Type:           ARM (Native)
  Role:                Non UI
  Parent Process:      launchd [1]
  
  OS Version:          Watch OS 6.1.1 (17S449)
  Release Type:        User
  Baseband Version:    n/a
  
  Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
  Exception Subtype: KERN_INVALID_ADDRESS at 0x00000004
  VM Region Info: 0x4 is not in any region.  Bytes before following region: 638972
        REGION TYPE              START - END     [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
        UNUSED SPACE AT START
  ---&gt;  
        __TEXT                 0009c000-000ac000 [   64K] r-x/r-x SM=COW  ...x/App Name
  
  Termination Signal: Segmentation fault: 11
  Termination Reason: Namespace SIGNAL, Code 0xb
  Terminating Process: exc handler [377]
  Triggered by Thread:  9
  
  Thread 0 name:
  Thread 0:
  0   libsystem_kernel.dylib          0x4381f864 semaphore_wait_trap + 8
  1   libdispatch.dylib               0x436dac26 _dispatch_sema4_wait + 12 (lock.c:139)
  2   libdispatch.dylib               0x436db09a _dispatch_semaphore_wait_slow + 104 (semaphore.c:132)
  3   FrontBoardServices              0x46de503e -[FBSSceneSnapshotRequestHandle performRequestForScene:] + 408 (FBSSceneSnapshotRequestHandle.m:67)
  4   FrontBoardServices              0x46de96ac -[FBSSceneSnapshotAction snapshotRequest:performWithContext:] + 218 (FBSSceneSnapshotAction.m:168)
  5   FrontBoardServices              0x46da4320 -[FBSSceneSnapshotRequest performSnapshotWithContext:] + 292 (FBSSceneSnapshotRequest.m:65)
  6   UIKitCore                       0x5ba6a000 __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke_3 + 168 (UIApplication.m:7655)
  7   FrontBoardServices              0x46de9568 -[FBSSceneSnapshotAction _executeNextRequest] + 244 (FBSSceneSnapshotAction.m:135)
  8   FrontBoardServices              0x46de91e0 -[FBSSceneSnapshotAction executeRequestsWithHandler:completionHandler:expirationHandler:] + 244 (FBSSceneSnapshotAction.m:87)
  9   UIKitCore                       0x5ba69f20 __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke_2 + 238 (UIApplication.m:7650)
  10  UIKitCore                       0x5ba69696 -[UIApplication _beginSnapshotSessionForScene:withSnapshotBlock:] + 772 (UIApplication.m:7582)
  11  UIKitCore                       0x5ba69e16 __65-[UIApplication _performSnapshotsWithAction:forScene:completion:]_block_invoke + 112 (UIApplication.m:7648)
  12  UIKitCore                       0x5b2c1110 -[UIScene _enableOverrideSettingsForActions:] + 40 (UIScene.m:1206)
  13  UIKitCore                       0x5b2c1330 -[UIScene _performSystemSnapshotWithActions:] + 112 (UIScene.m:1230)
  14  UIKitCore                       0x5ba69b90 -[UIApplication _performSnapshotsWithAction:forScene:completion:] + 382 (UIApplication.m:7647)
  15  UIKitCore                       0x5be89586 __98-[_UISceneSnapshotBSActionsHandler _respondToActions:forFBSScene:inUIScene:fromTransitionCont... + 146 (_UISceneSnapshotBSActionsHandler.m:54)
  16  UIKitCore                       0x5ba68fd4 _runAfterCACommitDeferredBlocks + 274 (UIApplication.m:3038)
  17  UIKitCore                       0x5ba5b3da _cleanUpAfterCAFlushAndRunDeferredBlocks + 198 (UIApplication.m:3016)
  18  UIKitCore                       0x5ba82702 _afterCACommitHandler + 56 (UIApplication.m:3068)
  19  CoreFoundation                  0x43b63644 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 18 (CFRunLoop.c:1758)
  20  CoreFoundation                  0x43b5f43c __CFRunLoopDoObservers + 350 (CFRunLoop.c:1868)
  21  CoreFoundation                  0x43b5f956 __CFRunLoopRun + 1150 (CFRunLoop.c:2910)
  22  CoreFoundation                  0x43b5f23a CFRunLoopRunSpecific + 370 (CFRunLoop.c:3192)
  23  GraphicsServices                0x46973cd0 GSEventRunModal + 96 (GSEvent.c:2246)
  24  UIKitCore                       0x5ba61580 UIApplicationMain + 1730 (UIApplication.m:4773)
  25  libxpc.dylib                    0x438fbcf0 _xpc_objc_main.cold.3 + 152
  26  libxpc.dylib                    0x438eca34 _xpc_objc_main + 184 (main.m:126)
  27  libxpc.dylib                    0x438ee934 xpc_main + 110 (init.c:1568)
  28  Foundation                      0x443f3156 -[NSXPCListener resume] + 172 (NSXPCListener.m:276)
  29  PlugInKit                       0x4b58b26c -[PKService run] + 384 (PKService.m:165)
  30  WatchKit                        0x52e9dafe WKExtensionMain + 62 (main.m:19)
  31  libdyld.dylib                   0x43715e82 start + 2
  
  Thread 1 name:
  Thread 1:
  0   libsystem_kernel.dylib          0x4381f814 mach_msg_trap + 20
  1   libsystem_kernel.dylib          0x4381eece mach_msg + 42 (mach_msg.c:103)
  2   CoreFoundation                  0x43b63946 __CFRunLoopServiceMachPort + 152 (CFRunLoop.c:2575)
  3   CoreFoundation                  0x43b5f9de __CFRunLoopRun + 1286 (CFRunLoop.c:2931)
  4   CoreFoundation                  0x43b5f23a CFRunLoopRunSpecific + 370 (CFRunLoop.c:3192)
  5   Foundation                      0x443bf398 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 180 (NSRunLoop.m:374)
  6   Foundation                      0x443bf2b4 -[NSRunLoop(NSRunLoop) runUntilDate:] + 76 (NSRunLoop.m:421)
  7   UIKitCore                       0x5badf012 -[UIEventFetcher threadMain] + 140 (UIEventFetcher.m:637)
  8   Foundation                      0x444c1b60 __NSThread__start__ + 708 (NSThread.m:724)
  9   libsystem_pthread.dylib         0x438ad1ac _pthread_start + 130 (pthread.c:896)
  10  libsystem_pthread.dylib         0x438b3f28 thread_start + 20
  
  Thread 2 name:
  Thread 2:
  0   libsystem_kernel.dylib          0x43836d04 __psynch_cvwait + 24
  1   libsystem_pthread.dylib         0x438b02c2 _pthread_cond_wait + 496 (pthread_cond.c:591)
  2   libsystem_pthread.dylib         0x438aca4a pthread_cond_wait + 38 (pthread_cancelable.c:558)
  3   Foundation                      0x444381f0 -[NSOperation waitUntilFinished] + 446 (NSOperation.m:737)
  4   Foundation                      0x444a5302 __NSOPERATIONQUEUE_IS_WAITING_ON_AN_OPERATION__ + 22 (NSOperation.m:2610)
  5   Foundation                      0x444222ee -[NSOperationQueue addOperations:waitUntilFinished:] + 128 (NSOperation.m:2618)
  6   WatchConnectivity               0x53f9871e __47-[WCSession handleUserInfoResultWithPairingID:]_block_invoke.491 + 540 (WCSession.m:1440)
  7   WatchConnectivity               0x53fa5608 -[WCFileStorage enumerateUserInfoResultsWithBlock:] + 1564 (WCFileStorage.m:505)
  8   WatchConnectivity               0x53f984ca __47-[WCSession handleUserInfoResultWithPairingID:]_block_invoke_2 + 284 (WCSession.m:1430)
  9   Foundation                      0x444a4794 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 10 (NSOperation.m:1541)
  10  Foundation                      0x443d2f7a -[NSBlockOperation main] + 74 (NSOperation.m:1560)
  11  Foundation                      0x444a63e2 __NSOPERATION_IS_INVOKING_MAIN__ + 22 (NSOperation.m:2184)
  12  Foundation                      0x443d2b96 -[NSOperation start] + 578 (NSOperation.m:2201)
  13  Foundation                      0x444a6b7c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 22 (NSOperation.m:2215)
  14  Foundation                      0x444a6798 __NSOQSchedule_f + 134 (NSOperation.m:2226)
  15  libdispatch.dylib               0x436d9846 _dispatch_call_block_and_release + 10 (init.c:1408)
  16  libdispatch.dylib               0x436da8b8 _dispatch_client_callout + 6 (object.m:495)
  17  libdispatch.dylib               0x436dc6f8 _dispatch_continuation_pop + 330 (inline_internal.h:2484)
  18  libdispatch.dylib               0x436dc08c _dispatch_async_redirect_invoke + 520 (queue.c:803)
  19  libdispatch.dylib               0x436e6eac _dispatch_root_queue_drain + 540 (inline_internal.h:2525)
  20  libdispatch.dylib               0x436e73e0 _dispatch_worker_thread2 + 98 (queue.c:6628)
  21  libsystem_pthread.dylib         0x438aecd2 _pthread_wqthread + 158 (pthread.c:2364)
  22  libsystem_pthread.dylib         0x438b3f10 start_wqthread + 20
  
  Thread 3:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 4:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 5:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 6 name:
  Thread 6:
  0   libsystem_kernel.dylib          0x43838c6c kevent_qos + 24
  1   libdispatch.dylib               0x436f2b74 _dispatch_kq_poll + 204 (event_kevent.c:736)
  2   libdispatch.dylib               0x436f280a _dispatch_kq_drain + 96 (event_kevent.c:809)
  3   libdispatch.dylib               0x436f2196 _dispatch_event_loop_poke + 162 (event_kevent.c:1918)
  4   libdispatch.dylib               0x436e32b8 _dispatch_mgr_queue_push + 110 (queue.c:5857)
  5   WatchConnectivity               0x53f9aa26 -[WCSession createAndStartTimerOnWorkQueueWithHandler:] + 150 (WCSession.m:1803)
  6   WatchConnectivity               0x53f90790 -[WCSession onqueue_sendMessageData:replyHandler:errorHandler:dictionaryMessage:] + 382 (WCSession.m:674)
  7   WatchConnectivity               0x53f901da __51-[WCSession sendMessage:replyHandler:errorHandler:]_block_invoke.256 + 190 (WCSession.m:630)
  8   Foundation                      0x444a4794 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 10 (NSOperation.m:1541)
  9   Foundation                      0x443d2f7a -[NSBlockOperation main] + 74 (NSOperation.m:1560)
  10  Foundation                      0x444a63e2 __NSOPERATION_IS_INVOKING_MAIN__ + 22 (NSOperation.m:2184)
  11  Foundation                      0x443d2b96 -[NSOperation start] + 578 (NSOperation.m:2201)
  12  Foundation                      0x444a6b7c __NSOPERATIONQUEUE_IS_STARTING_AN_OPERATION__ + 22 (NSOperation.m:2215)
  13  Foundation                      0x444a6798 __NSOQSchedule_f + 134 (NSOperation.m:2226)
  14  libdispatch.dylib               0x436e4c02 _dispatch_block_async_invoke2 + 80 (queue.c:525)
  15  libdispatch.dylib               0x436da8b8 _dispatch_client_callout + 6 (object.m:495)
  16  libdispatch.dylib               0x436dc6f8 _dispatch_continuation_pop + 330 (inline_internal.h:2484)
  17  libdispatch.dylib               0x436dc08c _dispatch_async_redirect_invoke + 520 (queue.c:803)
  18  libdispatch.dylib               0x436e6eac _dispatch_root_queue_drain + 540 (inline_internal.h:2525)
  19  libdispatch.dylib               0x436e73e0 _dispatch_worker_thread2 + 98 (queue.c:6628)
  20  libsystem_pthread.dylib         0x438aecd2 _pthread_wqthread + 158 (pthread.c:2364)
  21  libsystem_pthread.dylib         0x438b3f10 start_wqthread + 20
  
  Thread 7:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 8:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 9 name:
  Thread 9 Crashed:
  0   libdispatch.dylib               0x436eacec dispatch_channel_cancel + 6 (source.c:1020)
  1   WatchConnectivity               0x53f909c6 __81-[WCSession onqueue_sendMessageData:replyHandler:errorHandler:dictionaryMessage:]_block_invoke + 42 (WCSession.m:675)
  2   libdispatch.dylib               0x436da8b8 _dispatch_client_callout + 6 (object.m:495)
  3   libdispatch.dylib               0x436dc6f8 _dispatch_continuation_pop + 330 (inline_internal.h:2484)
  4   libdispatch.dylib               0x436ea81e _dispatch_source_invoke + 1758 (source.c:568)
  5   libdispatch.dylib               0x436e6eac _dispatch_root_queue_drain + 540 (inline_internal.h:2525)
  6   libdispatch.dylib               0x436e73e0 _dispatch_worker_thread2 + 98 (queue.c:6628)
  7   libsystem_pthread.dylib         0x438aecd2 _pthread_wqthread + 158 (pthread.c:2364)
  8   libsystem_pthread.dylib         0x438b3f10 start_wqthread + 20
  
  Thread 10:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 11:
  0   libsystem_pthread.dylib         0x438b3efc start_wqthread + 0
  
  Thread 9 crashed with ARM Thread State (32-bit):
      r0: 0x00000000    r1: 0x80000000      r2: 0x00000001      r3: 0x7fffffff
      r4: 0x16548f40    r5: 0x00000000      r6: 0x00000110      r7: 0x3f057e58
      r8: 0x00000000    r9: 0x00000000     r10: 0x00000000     r11: 0x00401600
      ip: 0x66e39628    sp: 0x3f057e30      lr: 0x53f909c7      pc: 0x436eacec
    cpsr: 0x80000030
  </code></pre>