Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Objective-C exceptions thrown inside methods invoked via NSInvocation are uncatchable

Whether you’re using Cedar or not, if you’ve upgraded to the iOS 4.0 SDK you may have run into some odd behavior with exception handling blocks not catching exceptions. Strangely, the problem isn’t due to the exceptions themselves (at least not in any obvious way), but with how you call functions that raise exceptions. An exception thrown from within a method you invoke directly will function as expected. However, if you invoke that same function indirectly using NSInvocation any exception thrown becomes uncatchable, crashing the current process regardless of any exception handling code.

This happens only when running against the currently available iOS 4.0 SDK. Exception handling for both direct and indirect invocations performs as expected when using the OS X 10.6 SDK and previous versions of the iPhone SDK.

You can reproduce this problem yourself easily enough. Just create any old iPhone project, and add the following code in a method you know will run (e.g. viewDidLoad on the main controller):

@try {
    NSException *exception = [NSException exceptionWithName:@"foo" reason:@"bar" userInfo:nil];
    [exception raise];
} @catch (NSException *x) {
    NSLog(@"========================> %@", x);

Works, right? Now try this (which should be functionally identical):

@try {
    NSException *exception = [NSException exceptionWithName:@"foo" reason:@"bar" userInfo:nil];

    SEL selector = @selector(raise);
    NSMethodSignature *signature = [exception methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

    [invocation setTarget:exception];
    [invocation setSelector:selector];
    [invocation invoke];
} @catch (NSException *x) {
    NSLog(@"========================> %@", x);

BOOM! Stack trace. Sad face.

Unfortunately, the OCHamcrest matcher library uses indirect method invocations to raise matcher failure exceptions. So, with iOS 4.0 rather than getting failure messages in your test output, you now get a stack trace and potentially a bunch of un-run tests.

Hopefully Apple will fix this soon.

  1. Yeah, it is an unfortunate bug in the iOS 4 Simulator platform. The bug does not manifest itself on the device. I originally reported the issue to the google toolbox guys (who had seen it before). It has since been posted to and confirmed as a bug by Greg Parker of Apple.

  2. It also manifests itself in NSProxy if you raise an exception within a forward invocation.

  3. Marco Sandrini says:

    Unluckily the problem is still present in simulators shipping with iOs SDKs 4.0.1 and 4.1 beta…

    Very very very frustrating…

  4. Adam Milligan says:

    Indeed! I was hoping a fix for this problem would be somewhere in that 5GB download, but Apple doesn’t seem to think it’s important enough to fix quickly.

  5. Marco Sandrini says:

    For us, this bug is a blocker, preventing upgrading to the latest version of the SDK (most likely we will move to some sort of dual installation of XCode using < 3.2 to run unit tests and > 3.2 to build the device version) . Oddly enough, to the present day the number of people who have raised this issue are below 5 (of which 3 have commented this post). Makes me wonder what is the common practice when developing sw for the iPhone…

  6. Adam Milligan says:

    Marco, how is the bug blocking you? I found it renders OCHamcrest (for example) unusable out of the box, but I was able to patch the way it reports errors to work around the problem (see [this commit]( on github). I used a little dynamic type hackery to change the implicit method to an explicit method; I’m told you can also use objc_msgSend() to fix the problem.

  7. Marco Sandrini says:

    We had two sources of problem, OCHamcrest (for which I thank you already for the patch) and some extra features we built on top of OCMock, for which I have been too lazy to go and replace NSInvocation(s) which calls to objc_msgSend as I was still hoping that I would not need to do any workaround (read: I was hoping Apple would fix this).

    Once more thanks for your help!!!

  8. Luke Redpath says:

    I’ve also run into this problem whilst working on my Objective-C mock library, Mocky [1]. I’ve filed a dupe: rdar://8237699, see

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *