## 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.