I am working on an iPhone app in Objective-C (using Xcode 6.1.1, and Parse), and I just got this mysterious NSInternalInconsistencyException
:
Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.":
So my question to the Stack Overflow community is:
How does someone read this stack trace to hunt down the actual source of the problem? I don't see any recognizable filenames, method calls or line numbers anywhere in this stack trace.
Or, if it's not a matter of simply reading the stack trace, and other techniques are involved, then what is the appropriate next step a developer should take to track down the source of this type of error?
Here is the full stack trace that outputs to my console:
2015-07-18 02:01:17.596 testapp[1276:60b] [Error]: Caught "NSInternalInconsistencyException" with reason "Tried to save an object with a pointer to a new, unsaved object.": ( 0 CoreFoundation 0x2f547f9b + 154 1 libobjc.A.dylib 0x39c94ccf objc_exception_throw + 38 2 CoreFoundation 0x2f547ec5 + 0 3 testapp 0x00205a29 -[PFObject(Private) resolveLocalId] + 384 4 testapp 0x00233d6d __32-[PFRESTCommand resolveLocalIds]_block_invoke + 24 5 testapp 0x00233783 +[PFRESTCommand forEachLocalIdIn:doBlock:] + 642 6 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 7 CoreFoundation 0x2f484043 + 98 8 CoreFoundation 0x2f483f67 + 162 9 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 10 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 11 CoreFoundation 0x2f484043 + 98 12 CoreFoundation 0x2f483f67 + 162 13 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 14 testapp 0x0023373f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 574 15 testapp 0x00233ba7 __42+[PFRESTCommand forEachLocalIdIn:doBlock:]_block_invoke + 62 16 CoreFoundation 0x2f484043 + 98 17 CoreFoundation 0x2f483f67 + 162 18 testapp 0x0023367f +[PFRESTCommand forEachLocalIdIn:doBlock:] + 382 19 testapp 0x00233ca3 -[PFRESTCommand forEachLocalId:] + 162 20 testapp 0x00233d3f -[PFRESTCommand resolveLocalIds] + 34 21 testapp 0x0023ee2f -[PFRESTCommandRunner _runCommandAsync:withCancellationToken:] + 110 22 testapp 0x0023e8c7 -[PFRESTCommandRunner runCommandAsync:withOptions:cancellationToken:] + 174 23 testapp 0x0023e7d7 -[PFRESTCommandRunner runCommandInBackground:inOperation:] + 42 24 testapp 0x00203667 __65+[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]_block_invoke_3 + 766 25 testapp 0x002854b3 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 + 214 26 libdispatch.dylib 0x3a17c833 + 10 27 libdispatch.dylib 0x3a183ad7 + 222 28 libdispatch.dylib 0x3a183d29 + 56 29 libsystem_pthread.dylib 0x3a2bebd3 _pthread_wqthread + 298 30 libsystem_pthread.dylib 0x3a2bea98 start_wqthread + 8 ).
I appreciate any help and insights you can offer me.
This particular example doesn't give the developer much to go on. So, the answer to your question in this case is "Google it." Really, the best clue from the stack trace is the line:
[PFObject(Private) _deepSaveAsync:withCurrentUser:sessionToken:]
The line above indicates a failed save using currentUser
, combined with the error message "Tried to save an object with a pointer to a new, unsaved object." should be enough to point to a probable cause.
As it turns out, this error is not uncommon and is bewildering why Parse does not fix it. It is generally caused by when your app is using anonymous Parse users and it attempts to save an object prior to the user object having been saved. Since the user object has not been saved, it has no objectId
and the save of the other object fails.
The solution is to check to see if the currentUser
object has an objectId
, and if not, save it first before trying to write to Parse.
// Prevent race condition for unsaved user
// Courtesy of: http://samwize.com/2014/07/15/pitfall-with-using-anonymous-user-in-parse/
if ([PFUser currentUser].objectId == nil) {
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
//do stuff later
}];
} else {
//do stuff now
}
NSInternalInconsistencyException
is thrown when a code enters a state which is never supposed to happen. Usually it indicates a bug made by those who wrote it, though sometimes it is possible to cause such condition by mis-using the library (doing something against what the docs say, for instance).
In other words, it's a bug, but if you didn't write the code that throws it, it's probably not yours. From this particular stack trace, the problem has to be in Parse.
Report the bug to the original developers. A good library must never throw that, regardless if you are misusing it or not. Until they fix it, the best you can do is try to workaround it, by doing what you were trying to do in some different way. If you have the sources of that library, you could try to debug and fix the problem yourself.
When you see such kind of errors and Xcode kicks you to AppDelegate, try to put in Xcode 2 kind of breakpoints
You will find these options in the left panel on the top
Breakpoint Navigator -> + (this simbol you'll find at the bottom side) -> Swift Error Breakpoint or/and Exception Breakpoint
Hope this will help you next time
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With