This is normal behavior. CoreData uses exception throwing & handling internally for some of its program flow. I talked to the CoreData people about this. It may seem odd, but that’s a design decision they made a long time ago.
When you hit the exception, make sure there’s none of your code in the backtrace between your call to -[NSManagedObjectContext save:] and the exception being thrown. Calling -save: is very likely to call back into your code, e.g. if you’re observing NSManagedObjectContextObjectsDidChangeNotification, and if you’re doing bad things when you’re handling those notification, obviously you’re at fault.
If you’re exiting the -save: method, and the return value is YES, everything is good.
Please note, that you should check the return value, do not use error != nil to check for an error. The correct check is:
NSError *error = nil;
BOOL success = [moc save:&error];
if (!success) {
// do error handling here.
}