28

I'm working on a Cocoa-Touch app, it uses CoreData and has some NSPersistentObject subclasses generated by the XCode model editor.

I've noticed that recently, when saving the context I get an error which has as user info the following part:

(gdb) po ui {
    "Dangling reference to an invalid object." = <null>;
    NSAffectedObjectsErrorKey = <dump #1 of someObject>;
    NSLocalizedDescription = "Operation could not be completed. (Cocoa error 1550.)";
    NSValidationErrorKey = <someKey pointing to someObject #1>;
    NSValidationErrorObject = <dump #2 of someOtherObject which points to the dump #1 object>;
    NSValidationErrorValue = { <list of someMoreObjects> };
}

There are on other keys in the user info dictionary.

All the dumps I get are valid objects, I've verified them all.

NSValidationErrorObject is an object which has an NSSet which contains objects of types dumped in NSAffectedObjectsErrorKey and NSValidationErrorValue. But all these objects are valid.

Furthermore, this happens randomly, sometimes it happens, sometimes not, and sometimes the list dumped in NSValidationErrorValue is longer, sometimes shorter.

I have no clue why this is happening, or what exactly the error is. Does anyone know what's going on? Any ideas what might cause this bizarre error?

Prody
  • 5,182
  • 6
  • 44
  • 62

9 Answers9

31

This error usually arises because a relationship is set improperly often when an object is left without a necessary reciprocal relationship. The object is "dangling" because the object graph says it should be in a relationship but it is just hanging off in space unconnected to any other object. The object is still valid in the sense that it is internal consistent but it's not in a valid place in the graph.

TechZen
  • 64,370
  • 15
  • 118
  • 145
  • The thing is, that I have three objects, A,B,C. A has many B's (NSSet). and both A and B each may have one C (relation). But I have not created a reverse relation in C, because I want to use the exact same C for both A and B and it seemed cleaner. Core data does give a warning about this but it worked when I tested and from what I read it's only a problem if I plan to do cascading automatic deletes. Do you think this could be the problem? – Prody Jan 05 '10 at 12:31
  • 2
    Possibly, but this is one of those problems whose resolution is in the details. The warning probably is telling you the source of the problem. With complex data structures, you should treat warnings as errors because the warning is usually telling you something might fail if the right circumstances line up. Check that both A and B have the same delete rule for C. In the error dump which objects are which i.e. is "someObject" and "someOtherObject" of class A,B or C? – TechZen Jan 05 '10 at 15:07
  • 1
    I've created dummy relations in C to A and B, set the reverse relations properly and set the delete actions to cascade. Now there are no more warnings, but I still get the same error :( – Prody Jan 05 '10 at 17:28
  • 1
    Btw the NSValidationErrorObject is of type C, and NSAffectedObjectsErrorKey and NSValidationErrorValue are both the same instance of B. – Prody Jan 05 '10 at 17:33
  • I've messed around with everything and I'm not exactly sure why this was happening, or why it stopped happening, but it's gone now. Since there's no other relevant answer, I'll mark this as accepted even tho it's not really the good answer. Thanks for trying tho :) – Prody Jan 06 '10 at 17:38
  • 2
    No idea how you fixed it? I would be interested. – Kamchatka Sep 27 '10 at 06:29
  • 1
    Now really a good answer? I found this answer very helpful. Thank you TechZen. – Oh Danny Boy Nov 19 '10 at 20:59
  • I have the same problem. I found that A's relationship B was deallocated, and B's `managedObjectContext` become nil at this moment. I don't know why! – Yozone W. Feb 25 '14 at 06:20
24

This question was asked a while back, but I just ran into it. It was not due in my case to a improperly set relationship technically. It was due to the object being set created in a different context, note not on a different thread just a different context on the same thread.

So look for threading issues if you are doing anything with thread with Core Data.

user1270061
  • 661
  • 6
  • 5
  • 1
    I am having a similar issue that is due to having multiple NSManagedObjectContext's for multithreaded core data code. Where do you suggest that I look for the threading issues? – Jason Nov 13 '12 at 07:39
  • 2
    I ran into this problem exactly because of mixing up contexts. Just make sure that you're establishing relationships only between objects belonging to the same context. – Engin Kurutepe Jan 29 '13 at 14:08
  • 1
    This was my issue as well. I was super confused because all of the relationships were seemingly valid (and set to "nullify" from both sides on a many-to-many) ... but I accidentally jumped a context in one instance and that was the end of that. – Ben Guild Sep 21 '16 at 07:50
13

Let's say you have a table "recipes" and a child table "ingredients". You then create a one-to-many relation from recipe's to ingredients and also create an inverse relationship (one-to-one) from ingredients to recipes. It makes sense to specify a delete rule of "cascade" from the recipes table because if you delete a recipe the ingredient should also be deleted. However, if you specify "no action" in the delete rule on the one-to-one relationship in ingredients you will get the dangling reference error when you try to delete an ingredient. Change the delete rule on the one-to-one relationship to "nullify" and this should correct the problem.

Chris
  • 131
  • 1
  • 2
6

I know it's long after the fact, but I've been fighting this problem on a Core Data Model that has ALL relationships set to Nullify. Kept getting these dangling references until I found a single setPrimitiveValue instead of setValue when I was adding to the relationships. Be careful, with relationships, you gotta be sure you do the right thing to let Core Data maintain the relationships for you!

p.pad
  • 529
  • 7
  • 11
4

I have another example of how to cause this problem: I have a MOC with a concurrency type of NSMainQueueConcurrencyType. Somewhere in the code I do this:

__block MyObjectType1 *obj1;
[managedObjectContext performBlockAndWait:^{
    obj1 = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:managedObjectContext];
}];
// some other stuff
[self saveContext];
__block NSManagedObjectID *object1ID;
[managedObjectContext performBlockAndWait:^{
    object1ID = [obj1 objectID];
}];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // do some slow-ish stuff
    [managedObjectContext performBlockAndWait:^{
        // create new object that has a relationship
        NSManagedObject *obj1_copy = [managedObjectContext objectWithID:object1ID];
        MyObjectType2 *obj2 = [NSEntityDescription insertNewObjectForEntityForName:@"OtherThing" inManagedObjectContext:managedObjectContext];
        obj2.relatedThing = obj1_copy;
    }];
    [self saveContext];
});

It turns out that sometimes, this fails. I still don't understand why, but forcing to get a non-temporary objectID seems to do the trick:

[context performBlockAndWait:^{
    NSError *error;
    [managedObjectContext obtainPermanentIDsForObjects:@[obj1] error:&error];
    object1ID = obj1.objectID;
}];
DaGaMs
  • 1,521
  • 17
  • 26
  • I should say that `saveContext` uses a `performBlockAndWait:` itself, so should be safe to use here, if I understand the queue concurrency types correctly... – DaGaMs Mar 30 '13 at 19:15
  • Thank you — this is the same problem I was running into! – mattsven Feb 03 '22 at 17:29
1

I had the same problem, finally I found the problem was that I was setting a relationship between two different managed object context.

Terry
  • 43
  • 8
0

Adding to original answer, there can be couple of reasons for this crash to occur. Read the error description carefully, It In my case i was setting up a relationship with object from another context.

Saqib Saud
  • 2,799
  • 2
  • 27
  • 41
0

I ran into this issue, and the problem had to do with different (or rather one nil) managed object contexts for entities that had a relationship. In my case, I created a relationship between the entities when both had nil Managed Object Contexts, and then added one of the entities to a MOC, and assumed the other would be added to the MOC as well. I assumed this because of the first two comments to the top answer on this SO thread, but that ended up being wrong.

So lesson learned: if you add an entity to a MOC, other entities that have relationships to it do not get dragged into the MOC along with it. You have to add them to the MOC also or Core Data will not be happy.

Community
  • 1
  • 1
sts54
  • 49
  • 9
-1

My problem was solved using this code:

[[CustomManagedObject managedObjectContext] performBlockAndWait:^{
        NSError *error;
        if (![[CustomManagedObject managedObjectContext] save:&error])
        {
            NSLog(@"Error in Saving: %@", [error.userInfo description]);
        }
    }];
Undo
  • 25,519
  • 37
  • 106
  • 129
Zeeshan
  • 4,194
  • 28
  • 32