ObjCRuntime.ObjCException indicates that an Objective-C exception was thrown by native iOS code and bubbled up into managed code during UIApplication.Main. In .NET for iOS / .NET MAUI this typically happens when a native API is called with invalid arguments or when a platform API throws (for example, NSInvalidArgumentException).
In .NET for iOS, Objective-C and managed exceptions use different runtimes. When a native Objective-C exception is thrown and the stack unwinder reaches managed frames, the Objective-C runtime cannot execute managed try/catch/finally blocks. Instead, the exception is surfaced as ObjCRuntime.ObjCException and the app terminates. This behavior is by design and is independent of whether the project targets .NET 8 or .NET 10.
Key points from the platform behavior:
- Native Objective-C exceptions (for example from UIKit or Foundation) are not reliably catchable with managed
catch (Exception) blocks.
- When such an exception occurs during
UIApplicationMain, it appears as an unhandled ObjCRuntime.ObjCException in Microsoft.iOS.dll, with the call stack rooted at UIApplication.Main / Program.Main.
- Only the MonoVM runtime supports unwinding native frames during managed exception handling; CoreCLR aborts the process when encountering this situation.
To troubleshoot in the app:
- Identify which native call is failing. The actual cause is usually in the first native frames above
UIApplicationMain (for example, a call into UIKit or a bound Objective-C API). Inspect the full stack trace and any logged NSException message (such as NSInvalidArgumentException).
- Fix the underlying misuse of the native API (for example, avoid passing
null/IntPtr.Zero where not allowed, or avoid calling selectors that are not available on the current OS version).
- Avoid relying on managed
try/catch around native calls to handle Objective-C exceptions; instead, prevent them by validating arguments and platform support before calling.
As an illustration from the platform documentation, the following code throws an Objective-C NSInvalidArgumentException in native code and cannot be reliably caught by a managed try/catch:
var dict = new NSMutableDictionary();
dict.LowlevelSetObject(IntPtr.Zero, IntPtr.Zero); // throws NSInvalidArgumentException
The Objective-C stack unwinder can unwind native frames, but it cannot correctly unwind managed frames or execute managed catch/finally blocks, so the process terminates with an ObjCRuntime.ObjCException.
In summary, upgrading from .NET 8 to .NET 10 does not change this fundamental behavior. The resolution is to locate and correct the native API usage that is causing the Objective-C exception, rather than attempting to handle ObjCRuntime.ObjCException in managed code.
References: