NSInternalInconsistencyException even inside performChanges block

I have a popular app and i'm seeing a sporadic crash that I don't understand:


Fatal Exception: NSInternalInconsistencyException
This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]


Here is the code, it crashes on line 3 (creationRequestForAssetFromImage) below:


       PHPhotoLibrary.shared().performChanges({
            guard
                let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: animatedImageFileURL),
                let albumChangeRequest = PHAssetCollectionChangeRequest.init(for: album),
                let placeholder = changeRequest.placeholderForCreatedAsset else {
                    WLog("ActionExecuter: error, couldn't init creationRequests")
                    completionBlock(nil)
                    return
            }
...


Clearly this IS in a performChanges block.


Full stack of crash, from line 3 above onwards:


Fatal Exception: NSInternalInconsistencyException
0  CoreFoundation                 0x184da6d8c __exceptionPreprocess
1  libobjc.A.dylib                0x183f605ec objc_exception_throw
2  Photos                         0x193cad220 -[PHPhotoLibrary recordInsertRequest:]
3  Photos                         0x193c3cf78 -[PHChangeRequestHelper initForNewObjectWithUUID:changeRequest:]
4  Photos                         0x193c6dfc4 -[PHAssetCreationRequest initForNewObjectWithUUID:]
5  Photos                         0x193c699c0 +[PHAssetCreationRequest _creationRequestForAssetUsingUUID:]
6  Photos                         0x193c69ce4 +[PHAssetCreationRequest creationRequestForAssetFromImageAtFileURL:]


I am wondering if this is some threading issue. Is there a rule about what thread performChanges et al have to be called from?


It seems to be slower devices that hit this: iOS 11 on an iPad Air 1 is the latest crash in the wild I saw of this one.

Thanks for any help

Replies

This sounds like a good candidate for a bug report, wirh crash logs attached.


One thought: Is it possible these crashes are coincident with a Photos library authorization alert appearing? Do you request authorization "manually" before trying to change the Photos library, or do you let it happend automatically?


If you're not using authorizationStatus/requestAuthorization before starting the update, it might be interesting to try doing that.

Thanks for the quick response.

To get this far, the user must have gotten to authorizationStatus == .authorized.

But one thing that occurred to me since my last post: on slower devices, it could be that these lines of code are running multiple times concurrently (on multiple threads). In that case, each instance will call its own performChanges()

Is that supported?

... also please keep in mind, I cannot reproduce this myself. So although I have full thread stacktraces from Fabric/etc, I don't have anything more

i have the same problems,https://forums.developer.apple.com/thread/110274 how do you fix it finally?

I had the same error and fixed it.

The cause on my project was that I accidentally called performChangesAndWait inside another performChanges (the latter is for creating a photo; the former is for creating an album to add the new photo to).

Once I un-nest the call blocks they work fine.