Ambiguous errors: NSInternalInconsistencyException mutating method

Terminating app due to uncaught exception

‘NSInternalInconsistencyException’, reason: ‘*** -[NSCFArray replaceObjectAtIndex:withObject:]: mutating method sent to immutable object’

Ok, so what does it actually mean and why am I getting this on a NSMutableArray…?

The error is not so much ‘ambiguous’ as downright misleading. My code clearly shows I am working with a mutable array;

NSMutableArray *items = [docket objectForKey:@"Times"];
[times setValue:startLabel.text forKey:@"Stop"];
[times setValue:[NSNumber numberWithFloat:diff] forKey:@"Total"];
[items replaceObjectAtIndex:[items count]-1 withObject:times];

So why the error? And why not the first time I run the app?

The answer is in the that last sentence, obviously when the object is constructed all is well, but later on (subsequent runs) the object has changed from mutable to non-mutable.

Normally that would occur when assigning an array to a mutable array, but in this case there is nowhere that stands out.

Enter the .pList !

We are storing the record in a plist file, which seems when you serialise a NSMutableArray it becomes an NSArray. Therefore when you read it back it is coming in as a non-mutable object.

NSMutableArray *items = [[NSMutableArray init] alloc];
[docket setValue:items ForKey:@"Times"];

however when it is read back;

NSMutableArray *items = [docket objectForKey:@"Times"];

it is changing the NSMutable to NSArray.

To make matters worse, this only crashes on the device, not on the simulator! Annoying.

The solution:

Ensure we type cast the NSArray into NSMutableArray when reading the value from the dictionary in the first place.

NSMutableArray *items = [[NSMutableArray alloc] initWithArray:[docket objectForKey:@"Times"]];

Another problem solved, and a happy client !