'Object's persistent store is not reachable...' on main thread

Found the answer.
The problem was nothing to do with threading. It was simply because there was already a write happening (Hence why people assume via Occam's Razor that it's a threading issue).

The real reason this error shows, is not to do with threading, like the internet says, but because a read/write is already in progress at the same time you're attempting another read/write.

[objectContext existingObjectWithID:objectID error:&error] performs I/O on the database in order to guarantee the object that you get back actually does exist. However, in my case, I was already performing a read higher up in the stack.

It was attempting to read the parent's children, then attempting to read each child. Where, in fact, I should be using [objectContext objectWithID:objectID] to fetch a faulted object, and then perform the appropriate I/O once it's required.

This is not only the correct way of doing things, it also saves memory by not loading fifty billion child entities when you only wanted the list of them.

Hope that helps clarify things for someone!


I want to share my case, which was related to NSManagedObjectContextDidSaveNotification:

I had this problem only in my UnitTests target, in the test cases which involved interaction with Core Data stack.

In my configuration of unit tests target each such case is preceded by beforeEach block having cleanUnitTestsDatabase() macros which performs a removal of Core Data's .sqlite3 file and reinstantiatiates a managed object context and persistent store coordinator to a new fresh state, so I have a whole database in a clean state each time I run in a new/next test case.

This caused the problem, because sometimes the following method was called after the current database had been axed because the current test case has been already passed and the next following test case has been entered already:

- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification {
    NSManagedObjectContext *savedContext = [notification object];

    if ([savedContext isEqual:self.mainQueueManagedObjectContext] == NO) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.mainQueueManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
        });
    }
}

I wanted to show an example of this problem of two reads of the NSManagedObject that will crash into each other and produce the error message in the Original question. but this will happen only if you have the NSManagedObjectContextDidSaveNotification set up, and are doing a mergeChangesFromContextDidSaveNotification... interestingly this notification was firing on a read of a valueForKey... not sure if there is a problem there.

    NSArray *theEvents = nil;
NSError *error = nil;

if ([currentObject valueForKey:@"event58Identifier"]) theEvents = [eventStore calendarItemsWithExternalIdentifier:[currentObject valueForKey:@"event58Identifier"]];

and how i solved it :0)

    NSArray *theEvents = nil;
NSError *error = nil;
NSString * identEvent = [currentObject valueForKey:@"event56Identifier"];

if (identEvent) theEvents = [eventStore calendarItemsWithExternalIdentifier:identEvent];

in any case, put in an NSLog and find as many saves as possible, because more than likely you don't need so many saves or reads, and try to get it all into one read or one write.