After adding a new Core Data model version to my app, I performed a lightweight migration, apparently successfully. The migrated file loaded fine, but upon the first attempt to access an attribute via a particular relationship, the app crashes with an NSRangeException: '*** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 35]'
. This relationship worked fine prior to the migration. I know from other posts here that 4294967295 is really -1
, but the only thing I can identify with 36 items in my app/data is that there are 36 total entities in the data model (for reference, the relationship that's being fetched has 58 items in its table).
The question:
My question is: based on the error I'm getting and the troubleshooting I've done below, is there a type of schema change that could pass the lightweight migration, but corrupt the data along the way, leading to the noted exception? I'm going to try breaking down the migration into smaller chunks over several versions to either isolate or avoid the issue, but it would be nice to be able to focus on specific schema changes that might be at fault.
The failure:
The failure occurs with the following code in "myobject":
[[self object2] text];
The object2 relationship is to-one, non-optional both ways and neither the forward nor inverse relationship was changed between data models. The text
attribute is likely not relevant because when the error occurs, awakeFromFetch
is not reached in object2. If I assign [self object2]
to a variable prior to the above statement, the assignment is successful and reports data: <fault>
.
The database:
Looking at the database in sqlite3, I notice the following:
- The index values for the forward and inverse relationships appear to be correct in each table.
- The object2 table has two columns for the inverse relationship instead of the one prior to migration (
ZMYOBJECT
as before and the additionalZ2_MYOBJECT
, which is empty for all rows). No other relationship were added to explain this column. - In the
Z_PRIMARYKEY
table, all entries post-migration show-1
forZ_MAX
, whereas prior to migration they showed zero for empty tables and the maximum row number for populated tables. Manually updatingZ_MAX
to the proper values did not help with the exception. AllZ_SUPER
values were correct.
I set up a mapping model to see if anything looked awry with the automatic mappings, but everything looked fine.
Overall schema changes:
In the source version of the data model, there were fourteen entities, of which only four had been populated with data (the app is still in development). Seven were top-level entities and seven were sub-entities of three of the top-level entities.
In the target version of the data model, twenty-two entities were added, some top-level and some sub-entities, with dozens of relationships, including some added to existing entities.
Some attributes and relationships were removed from existing entities and others were added. No data types or relationship settings were changed, no attributes or relationships were renamed, and no special mappings were required.
Update (2/25/12): As I started working on a new intermediate model, I remembered that I had changed the class (representedClassName) for a number of entities from NSManagedObject to an NSManagedObject subclass, but hadn't generated the class files. I didn't suspect that would cause an issue and, indeed, creating all of the class files did not help with the exception. I just wanted to note that as another change between models.
Conclusions:
This is a wild guess, but if the 36 entity count is not a coincidence, it seems that when "myobject" attempts to fault in "object2" it does not have a valid reference for the table and is attempting to load table number -1, causing the exception. The fact that a simple assignment of [self object2]
is successful, however, doesn't jibe with that conclusion.
Any ideas?