Crash when initializing CoreML model: Error Domain=com.apple.CoreML Code=0 "Error in declaring network."

Viewed 2801

I have an app on the App Store and I'm getting its error logs from Crashlytics. One of the most frequent errors the users get (and the one I failed miserably to reproduce) occurs when initializing a CoreML model in my project. Here is how I initialize the model:

class VisionManager: NSObject {
  /// Prediction model
  private static let model = MobileNet()

  ...

  override init() {
    super.init()

    guard let visionModel = try? VNCoreMLModel(for: VisionManager.model.model) else {
      // this case should never happen as we know for sure that the model we are using is an image classification model
      fatalError("The CoreML model being used is not compatible with the Vision framework.")
    }

    ...
  }

...
}

The error, as seen on Crashlytics, reads as follows:

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.apple.CoreML Code=0 "Error in declaring network." UserInfo={NSLocalizedDescription=Error in declaring network.}: file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.65.2/src/swift/stdlib/public/core/ErrorType.swift, line 181

And the stack trace shows that the error is thrown when executing the guard block. Actually, it goes deeper and shows that the error was thrown inside the static initialization at the top, when calling the initializer. The initializer, together with the whole MobileNet.swift class is automatically generated and looks like this:

init(contentsOf url: URL) throws {
  self.model = try MLModel(contentsOf: url)
}

/// Construct a model that automatically loads the model from the app's bundle
convenience init() {
  let bundle = Bundle(for: MobileNet.self)
  let assetPath = bundle.url(forResource: "MobileNet", withExtension:"mlmodelc")
  try! self.init(contentsOf: assetPath!)
}

It seems obvious that the error is thrown calling the init(contentsOf url: URL) method. However, since this is a generated file, I believe there isn't much I can do to tackle this error.

One possibility is that the compiled .mlmodelc file is not copied to the bundle somehow, and when trying to initialize the MobileNet object with that URL, we get an uncaught error. Is that even possible?

Any ideas or pointers on this issue is greatly appreciated.

2 Answers

It seems obvious that the error is thrown calling the init(contentsOf url: URL) method. However, since this is a generated file, I believe there isn't much I can do to tackle this error.

FYI, you can copy this generated file into a new file and use it instead to initialize the model (just rename the classes inside the new file). Then, try changing this line in your new file:

let bundle = Bundle(for: MobileNet.self)

to:

let bundle = Bundle.main

I'm not sure if this will fix your particular problem, but it did for me when I moved the generated file into a Cocoapod

Better to read the errors at the top of the output panel in Xcode. There should be an error something like this which shows the actual error: "A Core ML custom neural network layer requires an implementation named 'scaling' which was not found in the global namespace.

In my case, I had an unsupported layer in the model I used so I need to write MLCustomLayer. https://developer.apple.com/documentation/coreml/core_ml_api/creating_a_custom_layer

Related