Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unexpected start state'
Asked Answered
A

2

15

I've strange and rare to reproduce crash that happening on iOS 9. The question are How to fix this or What leads to this exception

As you can see traces not contains my code and crash happens on app start.

Last Exception Backtrace:
0   CoreFoundation                       0x0000000180a49900 __exceptionPreprocess + 124
1   libobjc.A.dylib                      0x00000001800b7f80 objc_exception_throw + 52
2   CoreFoundation                       0x0000000180a497d0 +[NSException raise:format:arguments:] + 104
3   Foundation                           0x00000001813bca08 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 84
4   UIKit                                0x00000001859f9f34 _prepareForCAFlush + 252
5   UIKit                                0x00000001859ff4f0 _beforeCACommitHandler + 12
6   CoreFoundation                       0x0000000180a00588 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 28
7   CoreFoundation                       0x00000001809fe32c __CFRunLoopDoObservers + 368
8   CoreFoundation                       0x00000001809fe75c __CFRunLoopRun + 924
9   CoreFoundation                       0x000000018092d680 CFRunLoopRunSpecific + 380
10  GraphicsServices                     0x0000000181e3c088 GSEventRunModal + 176
11  UIKit                                0x00000001857a4d90 UIApplicationMain + 200
12  MyAppName                            0x000000010009d200 main (main.m:14)
13  ???                                  0x00000001804ce8b8 0x0 + 0

Thread 0 Crashed:
0   libsystem_kernel.dylib               0x00000001805ec140 __pthread_kill + 8
1   libsystem_pthread.dylib              0x00000001806b4ef8 pthread_kill + 108
2   libsystem_c.dylib                    0x000000018055ddac abort + 136
3   MyAppName                            0x0000000100805bcc uncaught_exception_handler + 28
4   CoreFoundation                       0x0000000180a49c88 __handleUncaughtException + 648
5   libobjc.A.dylib                      0x00000001800b823c _objc_terminate() + 108
6   libc++abi.dylib                      0x00000001800aaf44 std::__terminate(void (*)()) + 12
7   libc++abi.dylib                      0x00000001800aab10 __cxa_rethrow + 140
8   libobjc.A.dylib                      0x00000001800b8120 objc_exception_rethrow + 40
9   CoreFoundation                       0x000000018092d728 CFRunLoopRunSpecific + 548
10  GraphicsServices                     0x0000000181e3c088 GSEventRunModal + 176
11  UIKit                                0x00000001857a4d90 UIApplicationMain + 200
12  MyAppName                            0x000000010009d200 main (main.m:14)
13  ???                                  0x00000001804ce8b8 0x0 + 0
Amalle answered 20/1, 2016 at 12:26 Comment(7)
What is written in the debugger console before the stack trace?Literalism
What you mean? This is part of log from crash reportAmalle
can you reproduce this crash in Xcode while debugging?Literalism
No, this happens only in release version, but what is your idea?Amalle
Look at this line from stack: 3 Foundation 0x00000001813bca08 -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 84. In debug mode you will see a message "Assertion failed in ...". It will help you at least to identify the failing source file.Literalism
Did you ever figure this out? It's happening to me, as well.Contraoctave
The same thing is happening to me, how did you fix it? (if you did)Zetes
C
4

I had the same crash, with reason: 'unexpected start state'.

Here is what was causing it:

  • I had a cell in a tableView, which contained a button with the title set to be an email address. When you press the button, I needed it to open the Mail app.

  • When it was opening the Mail app, my viewController which had the tableView, was reloading the table in traitCollectionDidChange. This tableView.reloadData() was causing the crash, most probably because the app was in transition between active state and background.

Here is what I did:

  • used a callback when pressing the email button:
class NewsDetailsFooterCell: UITableViewCell {

    //MARK: - Callbacks
    var sendEmail: ((_ emailUrl: URL) -> ())?

    //MARK: - IBActions
    @IBAction func openAuthorEmail(_ sender: UIButton) {

        guard let emailAddress = sender.titleLabel?.text, let url = URL(string: "mailto:\(emailAddress)") else { return }
        guard UIApplication.shared.canOpenURL(url) else { return }
        self.sendEmail?(url)
    }
}
  • In the tableView's cellForRowAt used the callback and modified a local variable which was responsible to block the tableView's reloadData in traitCollectionDidChange function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let newsFooterCell = tableView.dequeueReusableCell(withIdentifier: "NewsDetailsFooterCell") as! NewsDetailsFooterCell
            //other cell setup

    newsFooterCell.sendEmail = { [weak self] emailUrl in
        self?.viewModel.canReloadTable = false //this is the variable which I need to modify here
        UIApplication.shared.open(emailUrl, options: [:], completionHandler: nil)
    }
    return newsFooterCell
}
  • In traitCollectionDidChange I was reloading table's data only if the variable canReloadTable was true:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
   super.traitCollectionDidChange(previousTraitCollection)

   if #available(iOS 12.0, *) {
       //using this delegate method to trigger data reload to adapt to Dark/Light modes
       guard viewModel.canReloadTable else { return }
       tableView.reloadData()
   }
}
  • Finally, I was setting the variable canReloadTable back to true in viewDidAppear
   override func viewDidAppear(_ animated: Bool) {
       super.viewDidAppear(animated)

       viewModel.canReloadTable = true
   }

I hope this answer helps others, or at least gives a clue on where to investigate for a potential problem, since the error itself is not descriptive at all, and I spent some 1-2 hours investigating it and coming with a solution.

Causey answered 20/5, 2020 at 10:26 Comment(1)
I also had the same problem. Able to resolve it by adding dispatchque.main.async { self.tableView.reloadData()}Lactometer
R
4

Also, the same issue during the reloading UICollectionView in traitCollectionDidChange when changing the application theme.

I have the method updateTheme() where I update some kind of UI like layers, borders, shadows, etc. when the theme is changed.

  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    if #available(iOS 13.0, *), traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
      updateTheme()
    }
  }

And I will receive such message about termination:

*** Assertion failure in void _UIApplicationDrainManagedAutoreleasePool()(), UIApplication+AutoreleasePool.m:171
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unexpected start state'

when adding collectionView.reloadData() to updateTheme() method.

This happens when the application is minimized and the theme is changed. So interesting case, because everything works with views, buttons, labels, etc. but not with collections.

Generally, if a UIElement getting an update in the background thread applications getting crashed so whenever we want to update UI we need to update that UIElement in the main thread.

I would venture to assume that when the application is minimized, the traitCollectionDidChange method is not executed in the main thread, so you need to add DispatchQueue.main.async {} in order to update the UI in the main thread.

This change fixed the problem for me, I hope it will also help you, since the simple flag that you added, in my case, simply will not allow the interface to update when the theme is changed while the application is minimized.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    if #available(iOS 13.0, *), traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
      DispatchQueue.main.async {
        self.updateTheme()
      }
    }
  }
Retuse answered 28/4, 2021 at 11:11 Comment(1)
That is a good idea too! Didn't test it, but sounds valid.Causey

© 2022 - 2024 — McMap. All rights reserved.