Crash inside of Vision framework during VNImageRequestHandler use

Hello,

I've been dealing with a puzzling issue for some time now, and I’m hoping someone here might have insights or suggestions.

The Problem: We’re observing an occasional crash in our app that seems to originate from the Vision framework.

  • Frequency: It happens randomly, after many successful executions of the same code, hard to tell how long the app was working, but in some cases app could run for like a month without any issues.
  • Devices: The issue doesn't seem device-dependent (we’ve seen it on various iPad models).
  • OS Versions: The crashes started occurring with iOS 18.0.1 and are still present in 18.1 and 18.1.1.
  • What I suspected: The crash logs point to a potential data race within the Vision framework.

The relevant section of the code where the crash happens:

guard let cgImage = image.cgImage else {
    throw ...
}
let request = VNCoreMLRequest(model: visionModel)

try VNImageRequestHandler(cgImage: cgImage).perform([request]) // <- the line causing the crash

Since the code is rather simple, I'm not sure what else there could be missing here.

  • The images sent here are uniform (fixed size).
  • Model is loaded and working, the crash occurs random after a period of time and the call worked correctly many times. Also, the model variable is not an optional.

Here is the crash log:

libobjc.A	objc_exception_throw
CoreFoundation	-[NSMutableArray removeObjectsAtIndexes:]
Vision	-[VNWeakTypeWrapperCollection _enumerateObjectsDroppingWeakZeroedObjects:usingBlock:]
Vision	-[VNWeakTypeWrapperCollection addObject:droppingWeakZeroedObjects:]
Vision	-[VNSession initWithCachingBehavior:]
Vision	-[VNCoreMLTransformer initWithOptions:model:error:]
Vision	-[VNCoreMLRequest internalPerformRevision:inContext:error:]
Vision	-[VNRequest performInContext:error:]
Vision	-[VNRequestPerformer _performOrderedRequests:inContext:error:]
Vision	-[VNRequestPerformer _performRequests:onBehalfOfRequest:inContext:error:]
Vision	-[VNImageRequestHandler performRequests:gatheredForensics:error:]
OurApp	ModelWrapper.perform

And I'm a bit lost at this point, I've tried everything I could image so far.

I've tried to putting a symbolic breakpoint in the removeObjectsAtIndexes to check if some library (e.g. crash reporter) we use didn't do some implementation swap. There was none, and if anything did some method swizzling, I'd expect that to show in the stack trace before the original code would be called. I did peek into the previous functions and I've noticed a lock used in one of the Vision methods, so in my understanding any data race in this code shouldn't be possible at all. I've also put breakpoints in the NSLock variants, to check for swizzling/override with a category and possibly messing the locking - again, nothing was there.

There is also another model that is running on a separate queue, but after seeing the line with the locking in the debugger, it doesn't seem to me like this could cause a problem, at least not in this specific spot.

Is there something I'm missing here, or something I'm doing wrong?

Thanks in advance for your help!

Oh, right, and sorry for forgetting to write the crucial part in the post - what's the crash.

It's an out of bounds: -[NSMutableArray removeObjectsAtIndexes:]: index 1 in index set beyond bounds [0 .. 0] where it would look like the array was already cleared

I'm facing the exact same issue, and unfortunately I haven't figured out anything yet either. Please let us know if you figure anything out! I'll do the same.

Had the exact same issue happening as well. I had been trying to reproduce on iOS 17/macOS 14.5 unsuccessfully for a while after first getting the reports, right until I landed on this thread. All reports seem to be coming from iOS 18.X and macOS 15.X devices indeed. Any insights from Apple on what's the cause, or even better, a fix?

@BlazejStanek we found a workaround that may be useful to you as well. In our research on this problem, we discovered that this crash only seems to happen when you call .perform with more than one request. This was the case in our code base (and in Apple's sample app too). If you discover this is true for you, you can use our workaround.

What we did was unroll the perform calls, so instead of calling perform with our full array of requests, we iterate over the array of requests, and do a separate call to .perform on each one individually. We then accumulate the results of those calls and proceed from there.

Hopefully this helps. If not, good luck in your search.

I'm still experiencing these same issues in iOS 18.3 and up. I tried working around using Vision's VNImageRequestHandler by using my CoreML model directly, but I end up with a similar stack trace, resulting in the same crash:

"*** -[NSMutableArray removeObjectsAtIndexes:]: index 0 in index set beyond bounds for empty array"

0   CoreFoundation                	0x1a091e5fc __exceptionPreprocess + 164 (NSException.m:249)
1   libobjc.A.dylib               	0x19de99244 objc_exception_throw + 88 (objc-exception.mm:356)
2   CoreFoundation                	0x1a09b309c -[NSMutableArray removeObjectsAtIndexes:] + 960 (NSMutableArray.m:309)
3   Vision                        	0x1c1a314bc -[VNWeakTypeWrapperCollection _enumerateObjectsDroppingWeakZeroedObjects:usingBlock:] + 244 (VNWeakTypeWrapper.mm:126)
4   Vision                        	0x1c1a31154 -[VNWeakTypeWrapperCollection addObject:droppingWeakZeroedObjects:] + 172 (VNWeakTypeWrapper.mm:137)
5   Vision                        	0x1c1a36eec -[VNSession initWithCachingBehavior:] + 316 (VNSession.mm:352)
6   Vision                        	0x1c1c656f4 -[VNImageBuffer initWithCGImage:orientation:options:] + 56 (VNImageBuffer.mm:954)
7   CoreML                        	0x1bc73e534 -[_MLVNFrameworkHandle createPixelBufferFromCGImage:constraint:cropRect:cropAndScaleOption:options:error:] + 160 (_MLVNFrameworkHandle.m:275)
8   CoreML                        	0x1bc8093d4 +[MLFeatureValue(MLImageConversion) featureValueWithCGImage:constraint:options:error:] + 172 (MLFeatureValue+MLImageConversion.m:136)
9   CoreML                        	0x1bc8094f0 +[MLFeatureValue(MLImageConversion) featureValueWithCGImage:pixelsWide:pixelsHigh:pixelFormatType:options:error:] + 132 (MLFeatureValue+MLImageConversion.m:118)
10  MyApp                	                 0x10223b3f8 @nonobjc MLFeatureValue.__allocating_init(cgImage:pixelsWide:pixelsHigh:pixelFormatType:options:) + 40 (/<compiler-generated>:0)
11  MyApp                	                 0x10223b3f8 specialized mlModelInput.__allocating_init(imageWith:iouThreshold:confidenceThreshold:) + 40 (mlModel.swift:45)
12  MyApp                	                 0x10223b3f8 mlModelInput.__allocating_init(imageWith:iouThreshold:confidenceThreshold:) + 40 (/<compiler-generated>:0)

Is this issue being addressed soon, or might there at least be a viable workaround? It didn't seem to occur pre-iOS18/macOS15

I might have found a workaround, which might just work for your cases as well. As indicated in my previous post, I tried working around the issue by not using VNImageRequestHandler, but rather by using the CoreML model's predictions directly. In that case, I still passed it a CGImage. The generated CoreML model classes though also expose methods that accept a CVPixelBuffer as input - and the crash occurs in a function that converts the CGImage to a CVPixelBuffer.

I put symbolic breakpoints at -[VNWeakTypeWrapperCollection addObject:droppingWeakZeroedObjects:], which was consistently called before this change, and is no longer called after creating the CVPixelBuffers manually.

I hope this may help others as well - and I hope the problem stays away with this. If I still get issues, will keep you posted.

Crash inside of Vision framework during VNImageRequestHandler use
 
 
Q