CalendarEvent/get returns baseEventId for a normal, non-synthetic event

Issue Description

CalendarEvent/get returns baseEventId for a normal, non-synthetic event, with the value equal to the event’s own id.

baseEventId is intended to identify the underlying base event when the returned object represents a synthetic expanded recurrence instance.

Expected Behavior

For a normal CalendarEvent, baseEventId should be null.

For a synthetic recurrence instance, baseEventId should contain the id of the underlying real CalendarEvent.

Actual Behavior

For a normal event, Stalwart returns:

{
  "id": "<event-id>",
  "baseEventId": "<event-id>"
}

The event therefore identifies itself as its own base event.

Reproduction Steps

  1. Create a normal, non-recurring CalendarEvent.
  2. Fetch it with:
{
  "properties": ["id", "baseEventId"]
}
  1. Observe that baseEventId is returned with the same value as id.

Relevant Log Output

No error is reported.

Stalwart Version

v0.16.x

Installation Method

Built from source

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Looking at the source, this does appear to be a genuine bug. In get.rs, the BaseEventId property is populated unconditionally from the returned event’s own id, regardless of whether the event is a real event or a synthetic expanded recurrence instance:

JSCalendarProperty::BaseEventId => {
    result.insert_unchecked(
        JSCalendarProperty::BaseEventId,
        Value::Element(JSCalendarValue::Id(id.document_id().into())),
    );
}

There’s no check distinguishing a synthetic instance from the base event here, so every returned event (synthetic or not) gets its own id echoed back as baseEventId instead of null for normal events. This matches what you’re seeing. A human maintainer will need to confirm and patch this, since it’s a code-level fix rather than a configuration or docs issue.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in v0.16.22 (yet to be released).