Skip to content

get_missing_events does not respect min_depth #19812

Description

@timedoutuk

Description

The on_get_missing_events handler does not respect the min_depth field of the POST /_matrix/federation/v1/get_missing_events/{roomId} endpoint:

class FederationGetMissingEventsServlet(BaseFederationServerServlet):
PATH = "/get_missing_events/(?P<room_id>[^/]*)"
CATEGORY = "Federation requests"
async def on_POST(
self,
origin: str,
content: JsonDict,
query: dict[bytes, list[bytes]],
room_id: str,
) -> tuple[int, JsonDict]:
limit = int(content.get("limit", 10))
earliest_events = content.get("earliest_events", [])
latest_events = content.get("latest_events", [])
result = await self.handler.on_get_missing_events(
origin,
room_id=room_id,
earliest_events=earliest_events,
latest_events=latest_events,
limit=limit,
)
return 200, result

This means that Synapse will return potentially significantly more events than the sender requested, wasting time and potentially resulting in even more roundtrips.

Steps to reproduce

  • call /get_missing_events with a min_depth that is less than some of the events that would be returned
  • synapse returns a bunch of events below min_depth

Homeserver

N/A

Synapse Version

N/A

Installation Method

I don't know

Database

N/A

Workers

Multiple workers

Platform

N/A

Configuration

N/A

Relevant log output

2026-05-30T18:28:29.460190Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Attempting to gap fill missing events elapsed=12.959471226s limit=50 via=servername.example iteration=101 discovered=1648 min_depth=68402
2026-05-30T18:28:29.460346Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk:request:fed{dest="servername.example"}: conduwuit_service::federation::execute: Sending request method=POST url=https://matrix.servername.example:8448/_matrix/federation/v1/get_missing_events/!roomid
2026-05-30T18:28:29.534368Z TRACE transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk:request:fed{dest="servername.example"}: conduwuit_service::federation::execute: Received response from https://matrix.servername.example:8448 status=200 OK method=POST request_url=https://matrix.servername.example:8448/_matrix/federation/v1/get_missing_events/!roomid response_url=https://matrix.servername.example:8448/_matrix/federation/v1/get_missing_events/!roomid
2026-05-30T18:28:29.534395Z TRACE transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk:request:fed{dest="servername.example"}: conduwuit_service::federation::execute: Waiting for response body...
2026-05-30T18:28:29.535236Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk:request:fed{dest="servername.example"}: conduwuit_service::federation::execute: Got 200 for POST https://matrix.servername.example:8448/_matrix/federation/v1/get_missing_events/!roomid
2026-05-30T18:28:29.535282Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Got 20 events back from remote elapsed=13.034563404s
2026-05-30T18:28:29.535471Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.034752457s
2026-05-30T18:28:29.535545Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.034826528s
2026-05-30T18:28:29.535608Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.034888886s
2026-05-30T18:28:29.535702Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.034983079s
2026-05-30T18:28:29.535758Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48625 below min_depth 68402 elapsed=13.035038577s
2026-05-30T18:28:29.535846Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.035126887s
2026-05-30T18:28:29.535890Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48622 below min_depth 68402 elapsed=13.035171184s
2026-05-30T18:28:29.535933Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48590 below min_depth 68402 elapsed=13.035214707s
2026-05-30T18:28:29.535987Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48587 below min_depth 68402 elapsed=13.035268002s
2026-05-30T18:28:29.536095Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035376758s
2026-05-30T18:28:29.536152Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035433022s
2026-05-30T18:28:29.536200Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48633 below min_depth 68402 elapsed=13.035481615s
2026-05-30T18:28:29.536280Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035561297s
2026-05-30T18:28:29.536330Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035611791s
2026-05-30T18:28:29.536376Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035657714s
2026-05-30T18:28:29.536430Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035711498s
2026-05-30T18:28:29.536482Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035763367s
2026-05-30T18:28:29.536565Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035846586s
2026-05-30T18:28:29.536623Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035904578s
2026-05-30T18:28:29.536668Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Received PDU with depth 48629 below min_depth 68402 elapsed=13.035948729s
2026-05-30T18:28:29.536675Z TRACE transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}:get_missing_events_bulk: conduwuit_service::rooms::event_handler::fetch_and_handle_outliers: Finished get_missing_events elapsed=13.035956504s
2026-05-30T18:28:29.536682Z DEBUG transaction{id="txnid" origin="servername.example"}:pdu{room_id=!roomid event_id=$eventid}: conduwuit_service::rooms::event_handler::fetch_prev: Fetched 1659 missing events elapsed=13.037008972s

Anything else that would be useful to know?

Synapse does request a min_depth too:

path = _create_v1_path("/get_missing_events/%s", room_id)
return await self.client.post_json(
destination=destination,
path=path,
data={
"limit": int(limit),
"min_depth": int(min_depth),
"earliest_events": earliest_events,
"latest_events": latest_events,
},
timeout=timeout,
)

and looks like it expects that field to be respected:
if missing_prevs:
# We only backfill backwards to the min depth.
min_depth = await self._store.get_min_depth(pdu.room_id)
logger.debug("min_depth: %d", min_depth)
if min_depth is not None and pdu.depth > min_depth:
# If we're missing stuff, ensure we only fetch stuff one
# at a time.
logger.info(
"Acquiring room lock to fetch %d missing prev_events: %s",
len(missing_prevs),
shortstr(missing_prevs),
)
async with self._room_pdu_linearizer.queue(pdu.room_id):
logger.info(
"Acquired room lock to fetch %d missing prev_events",
len(missing_prevs),
)
try:
await self._get_missing_events_for_pdu(
origin, pdu, prevs, min_depth
)

and min_depth is even mentioned soon after too:
if missing_prevs:
# since this event was pushed to us, it is possible for it to
# become the only forward-extremity in the room, and we would then
# trust its state to be the state for the whole room. This is very
# bad. Further, if the event was pushed to us, there is no excuse
# for us not to have all the prev_events. (XXX: apart from
# min_depth?)
#
# We therefore reject any such events.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions