Hi everyone,
I'm having a regular issue with my project, using Parse Server. First, I call a Parse Cloud function to populate a user's data list :
var dataSet: Set<MyData>?
func loadData(withParameters parameters: [String : Any]) {
PFCloud.callFunction(inBackground: "loadData", withParameters: parameters) { (success, error) in
if let objects = success as? [[String : Any]] {
let dataTable: [MyData] = objects.map({ (object) -> MyData in
let myData = MyData(dataSource: PFObject(className: "MyData",
dictionary: object))
myData.dataSource?.objectId = object["objectId"] as? String
return myData
})
if self.dataSet == nil {
self.dataSet = []
}
self.dataSet = Set(dataTable)
}
}
}
On the code mentioned above, I have to set the objectId because without this, no matter how many objects I fetch from Parse, when I reduce the array to a set with the last instruction I end up with only one object in it.
However, although this works, when I call this function again to update user's data, I get this error on the myData.dataSource?.objectId = temp["objectId"] as? String line :
Attempted to change an objectId to one that's already known to the Offline Store.
Any idea? Thanks for your help.
Have same problem :(
@StratRob when calling a cloud function, the objects should already by hydrated as PFObject’s. Can you confirm that they are indeed not dictionaries? PFObject can be casted as dictionaries as they also conform to subscripting extensions.
I can confirm we got a new flood of this exact crash when deploying a new version of our app that upgraded from 1.15.3 to 1.15.4, with the associated Bolts upgrade, with no app changes that should have triggered something like this.
(apologies for the long stack trace...)
Attempted to change an objectId to one that's already known to the OfflineStore
Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x181306364 __exceptionPreprocess
1 libobjc.A.dylib 0x18054c528 objc_exception_throw
2 CoreFoundation 0x1813062ac -[NSException initWithCoder:]
3 Hidrate 0x100966d20 -[PFOfflineStore updateObjectIdForObject:oldObjectId:newObjectId:] (PFOfflineStore.m:1027)
4 Hidrate 0x1008fcb40 -[PFObject _notifyObjectIdChangedFrom:toObjectId:] (PFObject.m:1773)
5 Hidrate 0x1008fc738 -[PFObject set_state:] (PFObject.m:1729)
6 Hidrate 0x1008f92e4 -[PFObject(Private) _mergeFromServerWithResult:decoder:completeData:] (PFObject.m:1275)
7 Hidrate 0x1008f9128 -[PFObject(Private) _mergeAfterSaveWithResult:decoder:] (PFObject.m:1268)
8 Hidrate 0x1008f9abc __43-[PFObject(Private) handleSaveResultAsync:]_block_invoke (PFObject.m:1332)
9 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
10 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
11 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
12 Hidrate 0x1008c26c0 -[BFTask continueWithExecutor:block:cancellationToken:] (BFTask.m:368)
13 Hidrate 0x1008c2558 -[BFTask continueWithExecutor:withBlock:] (BFTask.m:316)
14 Hidrate 0x1008c1e30 +[BFTask taskFromExecutor:withBlock:] (BFTask.m:227)
15 Hidrate 0x1008f98b0 -[PFObject(Private) handleSaveResultAsync:] (PFObject.m:1327)
16 Hidrate 0x10090ac64 __79-[PFPinningEventuallyQueue _didFinishRunningCommand:withIdentifier:resultTask:]_block_invoke.115 (PFPinningEventuallyQueue.m:232)
17 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
18 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
19 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
20 Hidrate 0x1008c26c0 -[BFTask continueWithExecutor:block:cancellationToken:] (BFTask.m:368)
21 Hidrate 0x1008c2c34 -[BFTask continueWithBlock:] (BFTask.m:375)
22 Hidrate 0x10090a97c __79-[PFPinningEventuallyQueue _didFinishRunningCommand:withIdentifier:resultTask:]_block_invoke (PFPinningEventuallyQueue.m:231)
23 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
24 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
25 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
26 Hidrate 0x1008c244c -[BFTask runContinuations] (BFTask.m:308)
27 Hidrate 0x1008c1f94 -[BFTask trySetResult:] (BFTask.m:247)
28 Hidrate 0x1008bf358 -[BFTaskCompletionSource setResult:] (BFTaskCompletionSource.m:45)
29 Hidrate 0x1008c2934 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:354)
30 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
31 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
32 Hidrate 0x1008c244c -[BFTask runContinuations] (BFTask.m:308)
33 Hidrate 0x1008c1f94 -[BFTask trySetResult:] (BFTask.m:247)
34 Hidrate 0x1008bf358 -[BFTaskCompletionSource setResult:] (BFTaskCompletionSource.m:45)
35 Hidrate 0x1008c2a70 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 (BFTask.m:340)
36 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
37 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
38 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
39 Hidrate 0x1008c244c -[BFTask runContinuations] (BFTask.m:308)
40 Hidrate 0x1008c1f94 -[BFTask trySetResult:] (BFTask.m:247)
41 Hidrate 0x1008bf358 -[BFTaskCompletionSource setResult:] (BFTaskCompletionSource.m:45)
42 Hidrate 0x1008c2a70 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 (BFTask.m:340)
43 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
44 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
45 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
46 Hidrate 0x1008c244c -[BFTask runContinuations] (BFTask.m:308)
47 Hidrate 0x1008c1f94 -[BFTask trySetResult:] (BFTask.m:247)
48 Hidrate 0x1008bf358 -[BFTaskCompletionSource setResult:] (BFTaskCompletionSource.m:45)
49 Hidrate 0x1008c2a70 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 (BFTask.m:340)
50 Hidrate 0x1008c2860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
51 Hidrate 0x1008c88b0 __29+[BFExecutor defaultExecutor]_block_invoke_2 (BFExecutor.m:66)
52 Hidrate 0x1008c8e20 -[BFExecutor execute:] (BFExecutor.m:131)
53 Hidrate 0x1008c244c -[BFTask runContinuations] (BFTask.m:308)
54 Hidrate 0x1008c1f94 -[BFTask trySetResult:] (BFTask.m:247)
55 Hidrate 0x1008bf358 -[BFTaskCompletionSource setResult:] (BFTaskCompletionSource.m:45)
56 Hidrate 0x1008c2a70 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke_2 (BFTask.m:340)
57 Hidrate 0x1008c2918 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:348)
58 libdispatch.dylib 0x180c82a14 _dispatch_client_callout
59 libdispatch.dylib 0x180cc55ec _dispatch_sync_invoke_and_complete_recurse
60 libdispatch.dylib 0x180cc50f8 _dispatch_sync_wait
61 Hidrate 0x100936f00 PFThreadsafetySafeDispatchSync (PFThreadsafety.m:31)
62 libdispatch.dylib 0x180c82a54 _dispatch_call_block_and_release
63 libdispatch.dylib 0x180c82a14 _dispatch_client_callout
64 libdispatch.dylib 0x180cbe394 _dispatch_queue_override_invoke$VARIANT$armv81
65 libdispatch.dylib 0x180cc42a4 _dispatch_root_queue_drain
66 libdispatch.dylib 0x180cc4008 _dispatch_worker_thread3
67 libsystem_pthread.dylib 0x180f2b06c _pthread_wqthread
68 libsystem_pthread.dylib 0x180f2ab6c start_wqthread
Thanks to the Bolts dispatching strategy it's hard to see where in our app this is actually happening, but as we use no cloud functions I don't think it's specific to them.
Obviously not enough info for a real diagnosis, but what's your feeling? Might Bolts have changed something bad that screws up the order of some operations?
Bolts doesn’t swallow exceptions anymore, and I believe this is the reason why we see those now, i’ll Check with an older version if those were properly swallowed before
I can confirm that all PFConsistencyAssertion were previously caught in Bolts 1.8.* and now bolts don't catch them anymore.
We need to properly refactor those code paths to transofrm exceptions into errors which is problematic as it stands.
@StratRob , @ceramicatheist after much work into putting the SDK on a stable version for the Bolts 1.9.0, this exception is gonna stay, as you're mutating objects from the local datastore.
What's happening, is that you're changing the objectId from a known object, in previous versions this would yield an NSInternalInconsistencyException that would be caught by the bolts tasks runner.
This is an important error that should not be disregarded.
@ceramicatheist would you be able to share some code that would be responsible for this? Do you ever set manually an objectId on an objectWithoutData?
I did a sweep of our code looking for objectID, and we don't set it anywhere. We do extensively use the local store, but never assign an objectID.
(I do make a single dummy PFObject with a dummy ObjectID, but it's only used to construct a "must-fail" query and it never touches the local store.)
I should add (and maybe put in a separate issue?) that this was not the worst of the new crashes we saw. The most frequent was:
Fatal Exception: NSInternalInconsistencyException
User cannot be saved unless they are already signed up. Call signUp first.
0 CoreFoundation 0x181fa9d04 __exceptionPreprocess
1 libobjc.A.dylib 0x1811f8528 objc_exception_throw
2 CoreFoundation 0x181fa9c4c -[NSException initWithCoder:]
3 Hidrate 0x10277ea8c -[PFUser(Private) _checkSaveParametersWithCurrentUser:] (PFUser.m:142)
4 Hidrate 0x10272fd44 __81+[PFObject(Private) _deepSaveAsyncChildrenOfObject:withCurrentUser:sessionToken:]_block_invoke_3 (PFObject.m:465)
5 Hidrate 0x1026fe860 __55-[BFTask continueWithExecutor:block:cancellationToken:]_block_invoke (BFTask.m:331)
6 libdispatch.dylib 0x18192d088 _dispatch_call_block_and_release
7 libdispatch.dylib 0x18192d048 _dispatch_client_callout
8 libdispatch.dylib 0x181934090 _dispatch_queue_override_invoke$VARIANT$mp
9 libdispatch.dylib 0x18193a1c8 _dispatch_root_queue_drain
10 libdispatch.dylib 0x181939f10 _dispatch_worker_thread3
11 libsystem_pthread.dylib 0x181bd3120 _pthread_wqthread
12 libsystem_pthread.dylib 0x181bd2c20 start_wqthread
Which would occur when we sign up a new user authenticating with Facebook.
In the completion block of PFFacebookUtils.logInInBackground(withReadPermissions:), we immediately set some properties on the new User object and attempt to save it, and reliably get this exception.
Postponing that save with an async dispatch was enough to work around that particular problem.
I'm sorry, I wish I had nice succinct code snippets to share with you. The way Bolts works, it's very hard to tell which bit of our app is even at fault.
Ok, if you reliably have that error can you check the latest cocoapods version? 1.17.0-alpha.2. You should lot have the exception but a soft error
@StratRob I have been looking in depth into your issue, and I believe I found the solution.
When the localDatastore is enabled, you shoud always use [PFObject objectWithoutData:className objectId:objectId] to try to prefetch the object from the store in memory cache.
Your app is crashing because the new instances of PFObject's you're subsequently creating break the 1..1 mapping for the offline in memory cache. There's a potential fix, by changing the implementation of [PFObject className:@"" dictionary:@{}].
on another note, the objects in response to a PFCloud.runFunction call should contain the PFObjects, and I'M more enclined making sure that's the case. Can you double check that it isn't the case?
@ceramicatheist any chance you can isolate the call that yields that issue on merge?
@StratRob after further invesigation, I can confirm that if CloudCode returns proper Parse Object's they are already exposed as-is in the results. You don't need your initializer.
var dataSet: Set<MyData>?
func loadData(withParameters parameters: [String : Any]) {
PFCloud.callFunction(inBackground: "loadData", withParameters: parameters) { (success, error) in
if let objects = success as? [PFObject] {
let dataTable: [MyData] = objects.map({ (object) -> MyData in
return MyData(dataSource: object)
})
if self.dataSet == nil {
self.dataSet = []
}
self.dataSet = Set(dataTable)
}
}
}
This code should work. I'll be closing the issue now.
@ceramicatheist @iThinkersTeam I encourgage both of you to open a new issue.
@flovilmart
We've also encountered this issue.
I tried using the latest cocoapod version (which is 1.17.0-alpha.6), it will change ParseLiveQuery version (back to 1.x, the version still depend on SocketRocket, not Starscream) and conflict with the new Bolts API...
@ananfang what issue do you mean? You can use LiveQuery on branch 'release-2.4.0' (https://github.com/parse-community/ParseLiveQuery-iOS-OSX/pull/151) it's compatible with the latest Parse SDK alpha
@flovilmart
I just save a parse object included an array of pointers of other objects, it crash the app and show error: "Attempted to change an objectId to one that's already known to the Offline Store"
After changing Parse to branch 'release-1.17.0' and ParseLiveQuery to branch 'release-2.4.0', it will not crash the app, thanks for your effort.
@ananfang it doesn,t crash anymore but the operation errors :)
@flovilmart
After testing many times, this operation error still crash the app, not always, but about 50% to occur this issue.
The error message shows that:
Attempted to change an objectId to one that's already known to the OfflineStore. className: Story old: (null), new: 45le7HIrGE
Followings are my codes to save a Parse object with class name Story:
let story = Story() // Story is a PFObject subclass.
story.acl = /* Set ACL */
story.year = /* Set year */
story.month = /* Set month */
story.day = /* Set day */
story.locale = /* Set locale */
// Crash at follow line.
story.saveInBackground().continueWith(executor: BFExecutor.mainThread(), block: { task in
// Never enter this block.
})
There is a Live Query listen to this story (created, updated, entered and deleted)
@flovilmart
I found there are two macros in PFAssert.h (branch release-1.17.0):
PFPreconditionBailAndSetError and PFPreconditionBailOnError
Should be
PFPreconditionFailAndSetError and PFPreconditionFailOnError
@flovilmart
I've just sent a pull request to branch release-1.17.0 about this issue.
In the function - (void)updateObjectIdForObject:oldObjectId:newObjectId: of PFOfflineStore.m, if oldObjectId is nil but createdAt is not nil, means this object is just saved, and should update its reference in the local store without exception.
Hooray, I look forward to trying this out in our app and finally advancing from 1.15.3.
Are pre-built frameworks no longer available?
They should be
1.6.0 is the last tag with downloadable frameworks under it - everything since just has source code.
I apologize if I’m looking in the wrong place
On May 29, 2018, at 2:39 PM, Florent Vilmart notifications@github.com wrote:
They should be
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
Nope, you’re right my bad. They were supposedly automated, but it seems that it didn’t work as expected
Coming back a little bit late, but thank you very much for the help and explanation!