## Summary NotificationContentRecord (the native Swift record backing scheduleNotificationAsync 's content ) declares threadIdentifier as a @Field , so it's correctly parsed out of the JS-supplied object and even read back out when serializing a received notification. But toUNMutableNotificationContent() — the method that builds the actual outgoing UNMutableNotificationContent for a scheduled local notification — never assigns it. Every other field on that record ( title , body , categoryIdentifier , sound , attachments , interruptionLevel , ...) is copied over; threadIdentifier is the one silent exception. Net effect: passing threadIdentifier when scheduling a local notification compiles, is accepted by the native module, and does... nothing. iOS falls back to its own default "Automatic" notification grouping instead of the app-authored one that was requested. _Posted here, it's kind of a bug, but not an error. But I can't, neither I will, create an full application to trigger the issue_ ## Where packages/expo-notifications/ios/ExpoNotifications/Notifications/NotificationRecords.swift ```swift @Field public var categoryIdentifier: String? @Field var threadIdentifier: String? // <- declared, parsed from input, read back on output... ... func toUNMutableNotificationContent() -> UNMutableNotificationContent { let content = UNMutableNotificationContent() ... if let categoryIdentifier = categoryIdentifier { content.categoryIdentifier = categoryIdentifier } // ...threadIdentifier is never assigned to content anywhere in this function. if let sound = sound { ... ## Fix ```swift if let threadIdentifier = threadIdentifier { content.threadIdentifier = threadIdentifier } placed alongside the categoryIdentifier assignment. One-line native fix. The public NotificationContentInput TS type should also expose threadIdentifier as an input field — right now it's only documented on NotificationContentIos , the read/output-only type ( For the input type, see NotificationContentInput ), so even a caller who wanted to use this had no typed way to do it. ```ts /** * iOS notification-thread identifier, used to group related notifications together in * Notification Center / on the Lock Screen. * @platform ios */ threadIdentifier?: string; ## Reference implementation I already have a working `patch-package` fix for both changes above, build but not tested against `expo-notifications@57.0.7` (don't have iOS dev license yet). Happy to open this as a PR if useful — let me know. ## How I found this I was investigating explicit notification grouping on Android (see Support explicit Android notification grouping (`setGroup`/`setGroupSummary`) for local `scheduleNotificationAsync`) and, before assuming iOS was fine by default, went looking for the iOS equivalent of Android's `setGroup`/`setGroupSummary`. `threadIdentifier` is the iOS mechanism for that, and tracing it through the native module is how I found it's a no-op today. To be clear, this is **not** the same failure mode as the Android issue: iOS doesn't need an app-authored group summary to keep each notification's actions reachable (grouped notifications stay individually addressable via long-press regardless of `threadIdentifier`), so nothing is *broken* by this bug today for apps that don't rely on `threadIdentifier`. It's a silently-dead input, not a crash or a regression — but anyone trying to use it will see it fail with no error or explanation. ## Environment expo: ~57.0.8 expo-notifications: ~57.0.7 react-native: 0.86.0 Platform: iOS ``` ## Related issues #28580 — grouping for push notifications ( android.group / threadId in the FCM/APNs payload). Different code path (remote push, not local scheduleNotificationAsync ); the reporter there also tried threadId on iOS without success, which is consistent with what I found, but that issue is scoped to push and doesn't diagnose the local-notification root cause. Searched the repo for existing issues about threadIdentifier being dropped/ignored before filing — didn't find one covering this specific gap.