{"id":13659080,"url":"https://github.com/rickclephas/NSExceptionKt","last_synced_at":"2025-04-24T12:30:39.345Z","repository":{"id":47118897,"uuid":"514878174","full_name":"rickclephas/NSExceptionKt","owner":"rickclephas","description":"A Kotlin Multiplatform Library to improve crash reports on Apple platforms","archived":false,"fork":false,"pushed_at":"2024-10-21T18:56:50.000Z","size":346,"stargazers_count":175,"open_issues_count":3,"forks_count":12,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-22T11:16:22.463Z","etag":null,"topics":["kmm","kmp","kotlin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rickclephas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-17T15:14:52.000Z","updated_at":"2024-10-22T07:45:53.000Z","dependencies_parsed_at":"2024-04-15T20:32:11.768Z","dependency_job_id":"95594dbf-2327-49ca-ac12-167dbfce737e","html_url":"https://github.com/rickclephas/NSExceptionKt","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickclephas%2FNSExceptionKt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickclephas%2FNSExceptionKt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickclephas%2FNSExceptionKt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rickclephas%2FNSExceptionKt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rickclephas","download_url":"https://codeload.github.com/rickclephas/NSExceptionKt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223952666,"owners_count":17230931,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kmm","kmp","kotlin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native"],"created_at":"2024-08-02T05:01:05.118Z","updated_at":"2024-11-10T12:31:14.888Z","avatar_url":"https://github.com/rickclephas.png","language":"Kotlin","funding_links":[],"categories":["Libraries","iOS"],"sub_categories":["🔍 Analytics","Android samples"],"readme":"# NSExceptionKt\n\nA Kotlin Multiplatform Library to improve crash reports on Apple platforms.\n\n## Installation\n\nCheckout the implementation specific `README`s for usage and installation details:\n\n* [Crashlytics](NSExceptionKtCrashlytics/README.md)\n* [Bugsnag](NSExceptionKtBugsnag/README.md)\n\n## Why this library?\n\nIf you have been developing applications for Apple platforms with Kotlin Native, \nthen you have likely encountered crashes like the following:\n\n```\nFunction doesn't have or inherit @Throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError.\nIt is considered unexpected and unhandled instead. Program will be terminated.\nUncaught Kotlin exception: com.rickclephas.myapplication.Platform.TestException: Test exception 2\n    at 0   iosApp                              0x1020e88e7        kfun:kotlin.Exception#\u003cinit\u003e(kotlin.String?;kotlin.Throwable?){} + 119 \n    at 1   iosApp                              0x1020e8b1b        kfun:kotlin.RuntimeException#\u003cinit\u003e(kotlin.String?;kotlin.Throwable?){} + 119 \n    at 2   iosApp                              0x1020e8eff        kfun:kotlin.IllegalArgumentException#\u003cinit\u003e(kotlin.String?;kotlin.Throwable?){} + 119 \n    at 3   iosApp                              0x1020d3273        kfun:com.rickclephas.myapplication.Platform.TestException#\u003cinit\u003e(kotlin.String?;kotlin.Throwable?){} + 119 \n    ... and 38 more stack frames\nCaused by: kotlin.IllegalArgumentException: Test exception 1\n    at 0   iosApp                              0x1020ee457        kfun:kotlin.Throwable#\u003cinit\u003e(kotlin.String?){} + 95 \n    at 1   iosApp                              0x1020e884b        kfun:kotlin.Exception#\u003cinit\u003e(kotlin.String?){} + 91 \n    at 2   iosApp                              0x1020e8a7f        kfun:kotlin.RuntimeException#\u003cinit\u003e(kotlin.String?){} + 91 \n    at 3   iosApp                              0x1020e8e63        kfun:kotlin.IllegalArgumentException#\u003cinit\u003e(kotlin.String?){} + 91\n    ... and 39 more stack frames\n```\n\nSo far so good. You fix the crash and all is well. But what happens when such a crash occurs in production?!  \nWell, just like the above message said, the program will be [terminated](https://github.com/JetBrains/kotlin/blob/02901aeb106146274df7cff5686f8e376652fe2a/kotlin-native/runtime/src/main/cpp/Exceptions.cpp#L92).  \nAnd that is probably what you want anyway, so you open your favorite crash reporting tool and...:\n\n```\nException Type: EXC_CRASH (SIGABRT)\nCrashed Thread: 0\n\nThread 0 Crashed:\n0   libsystem_kernel.dylib          0x3980b2e60         __pthread_kill\n1   libsystem_pthread.dylib         0x39815b3bc         pthread_kill\n2   libsystem_c.dylib               0x30018f3f4         abort\n3   iosApp                          0x20230fc2c         konan::abort\n4   iosApp                          0x20231dca0         (anonymous namespace)::terminateWithUnhandledException::lambda::operator()\n5   iosApp                          0x20231db64         (anonymous namespace)::lambda::operator()\u003cT\u003e\n6   iosApp                          0x20231d924         (anonymous namespace)::terminateWithUnhandledException\n7   iosApp                          0x20231d8ac         (anonymous namespace)::processUnhandledException\n8   iosApp                          0x20231f73c         kotlin::ProcessUnhandledException\n9   iosApp                          0x202322cb4         Kotlin_ObjCExport_trapOnUndeclaredException\n```\n\nThe good news: you know your app crashed 🥸. The bad news: there is no useful stacktrace 🥹.\n\nFortunately we can [log](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native/set-unhandled-exception-hook.html) \nsuch unhandled exceptions in Kotlin before the app is terminated! \n\n## The challenges\n\nWhile we can use any Objective-C crash reporting SDK we like, \nthe concept of error handling is very different between Kotlin and ObjC/Swift.\n\n\u003e On the Kotlin side all exceptions are unchecked, but on the Swift side they are all checked.  \n\u003e That's why we need that [`@Throws` annotation](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-throws/), \n\u003e which tells Kotlin what exception types a function is expected to throw.\n\nWhen you try to log your unhandled `Exception`s, you'll soon realise that most SDKs only expose APIs to log `NSError`s.\nUnfortunately you can't just map an `Exception` to a `NSError`, for one you would lose the stacktrace.\n\nIn the rare case that you can log your exception (e.g. with Crashlytics via the [ExceptionModel] class),\nthe logged exception will be marked as non-fatal and the real crash is logged as well (resulting in two reports).\n\n[ExceptionModel]: https://firebase.google.com/docs/reference/swift/firebasecrashlytics/api/reference/Classes/ExceptionModel\n\nSo we basically need to:\n* log a fatal error from Kotlin\n* attach a stacktrace to it\n* preferably attach the caused by exceptions (with their stacktrace)\n* prevent the Kotlin termination from being logged \n\n## Acknowledgments\n\n[Kermit](https://github.com/touchlab/Kermit) by [Touchlab](https://touchlab.co/) \nand specifically [@kpgalligan](https://twitter.com/kpgalligan) have been a great inspiration for this project.\n\nI would also like to thank Firebase, Bugsnag and Sentry for publishing the sources of their SDKs.  \nWithout those sources projects like these wouldn't exist.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickclephas%2FNSExceptionKt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frickclephas%2FNSExceptionKt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frickclephas%2FNSExceptionKt/lists"}