Repository navigation
PARTSTAT change on a single occurrence of a recurring event triggers METHOD:REQUEST re-invite to all other attendees #60452
Description
Bug description
When an attendee accepts or declines a single occurrence of a recurring event, a recurrence exception (VEVENT with RECURRENCE-ID) is created. This modification to the calendar object causes Nextcloud to send a METHOD:REQUEST email to all other attendees, even though nothing changed for them.
This does not happen for single (non-recurring) events, where a PARTSTAT change correctly results in only a METHOD:REPLY to the organizer.
Related: nextcloud/calendar#6535 (notification spam), nextcloud/calendar#7771 (accept creates recurrence exception instead of updating master PARTSTAT), nextcloud/calendar#7850 (recurring event exception handling), #60451 (iMIP mail body issues for recurring events).
Setup:
- Calendar app: 6.4.0
- dav: 1.36.0
- All users on the same instance, invited via the internal user picker (principal-based scheduling).
- Attendees use Thunderbird 128.x via CalDAV.
Scenario 1: Attendee declines a single occurrence
User A creates a weekly recurring event "Weekly 3x" (3 occurrences), adds User B and User C as attendees. Both accept the series via Thunderbird. User B then declines only the 2026-05-12 occurrence via Thunderbird.
User A (organizer) receives a correct METHOD:REPLY with RECURRENCE-ID for 2026-05-12 and PARTSTAT=DECLINED. The mail says "User B has declined your invitation" with the correct date. This is correct.
User C (other attendee) receives a METHOD:REQUEST re-invite for the entire series:
METHOD:REQUEST
BEGIN:VEVENT
UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DTSTART;TZID=Europe/Berlin:20260505T113000
RRULE:FREQ=WEEKLY;COUNT=3;BYDAY=TU
SUMMARY:Weekly 3x
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-b@example.com
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-c@example.com
ORGANIZER;CN=admin:mailto:user-a@example.com
END:VEVENT
BEGIN:VEVENT
UID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
DTSTART;TZID=Europe/Berlin:20260512T113000
RECURRENCE-ID;TZID=Europe/Berlin:20260512T113000
ATTENDEE;PARTSTAT=DECLINED:mailto:user-b@example.com
ATTENDEE;PARTSTAT=ACCEPTED:mailto:user-c@example.com
ORGANIZER;CN=admin:mailto:user-a@example.com
END:VEVENT
Thunderbird at User C: "admin has invited you to Weekly 3x"
Nextcloud mail body: "admin möchte dich zu 'Weekly 3x' einladen."
User C already accepted. Nothing changed for User C. This email provides no useful information.
Scenario 2: Attendee accepts a single occurrence
User A creates a daily recurring event, adds User B and User C. User C accepts a single occurrence via the Nextcloud Calendar web UI (which creates a recurrence exception due to nextcloud/calendar#7771).
Result: User B receives a METHOD:REQUEST re-invite. The mail says "admin would like to invite you to 'Daily Test'" with the date of the first occurrence (in the past).
Scenario 3: Attendee removes event from calendar
Same setup. User C deletes the event in Thunderbird.
Result: User B again receives a METHOD:REQUEST re-invite.
Control test: Accepting the entire series
User A creates a weekly recurring event, adds User B and User C. User B accepts the entire series via Thunderbird iMIP ("Accept all").
Result: User C does not receive any email. Only User A receives the METHOD:REPLY. This is the correct behavior.
Control test: Single (non-recurring) event
User A creates a single event, adds User B and User C. User B accepts via Thunderbird.
Result: User C does not receive any email. Only User A receives the METHOD:REPLY. This is the correct behavior.
Pattern:
| Scenario | Other attendees receive re-invite? | Correct? |
|---|---|---|
| Single event: attendee accepts | No | Yes |
| Series: attendee accepts entire series | No | Yes |
| Series: attendee accepts single instance | Yes | No |
| Series: attendee declines single instance | Yes | No |
| Series: attendee deletes event | Yes | No |
The re-invite is only triggered when the PARTSTAT change creates a recurrence exception (VEVENT with RECURRENCE-ID). Operations that do not create exceptions behave correctly.
Steps to reproduce
- User A creates a weekly recurring event in the Nextcloud Calendar web UI (e.g. 3 occurrences), adds User B and User C as attendees via the user picker.
- User B accepts the entire series via Thunderbird iMIP.
- User C accepts the entire series via Thunderbird iMIP.
- User B declines a single occurrence via Thunderbird.
- User C receives a
METHOD:REQUESTre-invite email for the entire series.
Expected behavior
A PARTSTAT change by one attendee should only generate a METHOD:REPLY to the organizer. Other attendees should not receive any email, regardless of whether the change creates a recurrence exception internally.
With N attendees, every accept/decline on a single instance currently generates up to N-1 unnecessary emails. On an instance with ~600 users, this creates significant email noise.
Nextcloud Server version
33
Operating system
Debian/Ubuntu
PHP engine version
PHP 8.3
Web server
Apache (supported)
Database engine version
MySQL
Is this bug present after an update or on a fresh install?
Upgraded to a MAJOR version (ex. 31 to 32)
Are you using the Nextcloud Server Encryption module?
Encryption is Disabled
What user-backends are you using?
- Default user-backend (database)
- LDAP/ Active Directory
- SSO - SAML
- Other
Configuration report
{
"system": {
"passwordsalt": "***REMOVED SENSITIVE VALUE***",
"secret": "***REMOVED SENSITIVE VALUE***",
"trusted_domains": [
"***REMOVED SENSITIVE VALUE***",
"***REMOVED SENSITIVE VALUE***",
"***REMOVED SENSITIVE VALUE***"
],
"datadirectory": "***REMOVED SENSITIVE VALUE***",
"dbtype": "mysql",
"version": "33.0.3.2",
"overwrite.cli.url": "***REMOVED SENSITIVE VALUE***",
"dbname": "***REMOVED SENSITIVE VALUE***",
"dbhost": "***REMOVED SENSITIVE VALUE***",
"dbport": "",
"dbtableprefix": "oc_",
"mysql.utf8mb4": true,
"dbuser": "***REMOVED SENSITIVE VALUE***",
"dbpassword": "***REMOVED SENSITIVE VALUE***",
"installed": true,
"instanceid": "***REMOVED SENSITIVE VALUE***",
"htaccess.RewriteBase": "\/",
"maintenance_window_start": 1,
"maintenance": false,
"default_phone_region": "de",
"mail_smtpmode": "smtp",
"mail_smtpsecure": "ssl",
"mail_sendmailmode": "smtp",
"mail_from_address": "***REMOVED SENSITIVE VALUE***",
"mail_domain": "***REMOVED SENSITIVE VALUE***",
"mail_smtphost": "***REMOVED SENSITIVE VALUE***",
"mail_smtpauth": 1,
"mail_smtpname": "***REMOVED SENSITIVE VALUE***",
"mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
"mail_smtpport": "465",
"theme": "",
"loglevel": 2,
"config_preset": 9,
"app_install_overwrite": [
"fairmeeting",
"jitsi",
"bbb"
],
"memcache.local": "\\OC\\Memcache\\APCu"
}
}List of activated Apps
Enabled:
- activity: 6.0.0
- app_api: 33.0.0
- bruteforcesettings: 6.0.0
- calendar: 6.4.0
- circles: 33.0.0
- cloud_federation_api: 1.17.0
- comments: 1.23.0
- contacts: 8.4.5
- contactsinteraction: 1.14.1
- dashboard: 7.13.0
- dav: 1.36.0
- federatedfilesharing: 1.23.0
- federation: 1.23.0
- files: 2.5.0
- files_downloadlimit: 5.1.0
- files_pdfviewer: 6.0.0
- files_reminders: 1.6.0
- files_sharing: 1.25.2
- files_trashbin: 1.23.0
- files_versions: 1.26.0
- firstrunwizard: 6.0.0
- guests: 4.7.2
- logreader: 6.0.0
- lookup_server_connector: 1.21.0
- mail: 5.7.15
- nextcloud_announcements: 5.0.0
- notifications: 6.0.0
- oauth2: 1.21.0
- password_policy: 5.0.0
- photos: 6.0.0
- privacy: 5.0.0
- profile: 1.2.0
- provisioning_api: 1.23.0
- recommendations: 6.0.0
- related_resources: 4.0.0
- richdocuments: 10.1.3
- serverinfo: 5.0.0
- settings: 1.16.0
- sharebymail: 1.23.0
- support: 5.0.0
- survey_client: 5.0.0
- text: 7.0.1
- theming: 2.8.0
- twofactor_backupcodes: 1.22.0
- twofactor_totp: 15.0.0
- updatenotification: 1.23.0
- user_status: 1.13.0
- viewer: 6.0.0
- weather_status: 1.13.0
- webhook_listeners: 1.5.0
- whiteboard: 1.5.8
- workflowengine: 2.15.0
Disabled:
- admin_audit: 1.23.0
- bbb: 2.9.1 (installed 2.9.1)
- calendar_resource_management: 0.12.1 (installed 0.12.1)
- collectives: 4.4.0 (installed 4.4.0)
- deck: 1.17.1 (installed 1.17.1)
- encryption: 2.21.0
- fairmeeting: 0.22.5 (installed 0.22.5)
- files_external: 1.25.1
- integration_mattermost: 3.1.0 (installed 3.1.0)
- jitsi: 0.19.0 (installed 0.19.0)
- richdocumentscode: 25.4.904 (installed 25.4.904)
- riotchat: 0.20.0 (installed 0.20.0)
- spreed: 23.0.4 (installed 23.0.4)
- suspicious_login: 11.0.0
- systemtags: 1.23.0 (installed 1.22.0)
- tables: 2.1.1 (installed 2.1.1)
- testing: 1.23.0
- twofactor_nextcloud_notification: 7.0.0
- user_ldap: 1.24.0Nextcloud Signing status
No errors have been found.Nextcloud Logs
Additional info
This is a test instance used for app development. The bug was reproduced using only the Calendar web UI and Thunderbird iMIP. No third-party apps are involved in the iMIP/iTIP code path.
Related issues:
- email body for recurring event modifications does not show which occurrence was affected #60451 (iMIP mail body does not show which occurrence was affected)
- Need a setting to disable notifications about creating/editing calendar events where I am in the attendees list. calendar#6535 (need a setting to disable notifications)
- Missing “apply to all/this/this and following” options for recurring events in calendar #12142 calendar#7771 (accept creates recurrence exception instead of updating master PARTSTAT)
- Handle recurring event modification/excemptions better calendar#7850 (recurring event exception handling)
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTriaged
Activity
fix(dav): suppress iTip REQUEST for PARTSTAT-only occurrence overrides
fix(dav): suppress iTip REQUEST for PARTSTAT-only occurrence overrides
Rikdekker commentedon Oct 27, 2026
We looked into this and can reproduce it on 35.0.2 (attendee declines one occurrence via CalDAV, the other attendee receives "Invitation updated") and on master against TipBroker (after #64317): when an attendee declines one occurrence, processMessageReply adds an override to the organizer's copy, and parseEventForOrganizer then flags significantChange for every other attendee, although nothing changed for them. There are two reasons: their set of instance keys grew (count($oldAttendeeInstances) !== count($newAttendeeInstances)), and significantChangeHash is computed over the whole object, so any new override changes it for everyone. The organizer adding or removing someone on a single occurrence triggers the same path.
I opened #65971 with a fix that decides significance per attendee, over the occurrences they take part in. A new override that matches the occurrence it replaces doesn't count. It comes with unit tests for these scenarios: five of them fail on master, and the CalDAV suite stays green. On a 35.0.2 instance, together with #64635, every scenario now mails only the affected attendee, and the other attendees' copies are still updated. @DerDreschner, I saw this issue is assigned to you. Happy to adjust the PR if you had a different approach in mind.
AI disclosure: the analysis, the fix and the tests were made with the help of Claude Code (Anthropic). I reviewed and verified the results myself.