Repository: matrix-org/synapse

Issue:
 purge_up_to_ts in purge history api is broken
```
# curl -X POST --data '{ "delete_local_events": true, "purge_up_to_ts": 1523127593000 }' 'http://127.0.0.1:8008/_matrix/client/r0/admin/purge_history/!redacted/?access_token=redacted'
{
    "errcode": "M_UNKNOWN",
    "error": "Internal server error"
}

```

```
2018-04-07 22:01:15,933 - synapse.http.server - 191 - ERROR - POST-1797969- Failed handle request synapse.http.server._async_render on <synapse.rest.ClientRestResource object at 0x7f4bddc09290>: <XForwardedForRequest at 0x7f4b7da44290 method=POST uri=/_matrix/client/r0/admin/purge_history/!redacted/?access_token=<redacted> clientproto=HTTP/1.1 site=8008>: Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 651, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1355, in gotResult
    _inlineCallbacks(r, g, deferred)
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1297, in _inlineCallbacks
    result = result.throwExceptionIntoGenerator(g)
  File "/usr/lib/python2.7/dist-packages/twisted/python/failure.py", line 389, in throwExceptionIntoGenerator
    return g.throw(self.type, self.value, self.tb)
--- <exception caught here> ---
  File "/usr/lib/python2.7/dist-packages/synapse/http/server.py", line 162, in wrapped_request_handler
    yield request_handler(self, request, request_metrics)
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1297, in _inlineCallbacks
    result = result.throwExceptionIntoGenerator(g)
  File "/usr/lib/python2.7/dist-packages/twisted/python/failure.py", line 389, in throwExceptionIntoGenerator
    return g.throw(self.type, self.value, self.tb)
  File "/usr/lib/python2.7/dist-packages/synapse/http/server.py", line 307, in _async_render
    callback_return = yield callback(request, **kwargs)
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1299, in _inlineCallbacks
    result = g.send(result)
  File "/usr/lib/python2.7/dist-packages/synapse/rest/client/v1/admin.py", line 173, in on_POST
    room_id, stream_ordering,
exceptions.TypeError: 'NoneType' object is not iterable
```

debian stretch and matrix-synapse 0.27.2-1


Discussion:
Sigh. Yes. Apparently if the server can't find *any* events in the room after the cutoff time it throws this exception.

The problem is here:

```
            (_, depth, _) = (
                yield self.store.get_room_event_after_stream_ordering(
                    room_id, stream_ordering,
                )
            )
```

`get_room_event_after_stream_ordering` returns None, which then can't be assigned to `(_, depth, _)`

Please fix this Issue, my log file get bigger and bigger.

```
# grep NoneType /var/log/matrix-synapse/homeserver.log | wc -l
1768
```

Resolving patch:
diff --git a/synapse/rest/client/v1/admin.py b/synapse/rest/client/v1/admin.py
--- a/synapse/rest/client/v1/admin.py
+++ b/synapse/rest/client/v1/admin.py
@@ -168,11 +168,24 @@ def on_POST(self, request, room_id, event_id):
                 yield self.store.find_first_stream_ordering_after_ts(ts)
             )
 
-            (_, depth, _) = (
+            room_event_after_stream_ordering = (
                 yield self.store.get_room_event_after_stream_ordering(
                     room_id, stream_ordering,
                 )
             )
+            if room_event_after_stream_ordering:
+                (_, depth, _) = room_event_after_stream_ordering
+            else:
+                logger.warn(
+                    "[purge] purging events not possible: No event found "
+                    "(received_ts %i => stream_ordering %i)",
+                    ts, stream_ordering,
+                )
+                raise SynapseError(
+                    404,
+                    "there is no event to be purged",
+                    errcode=Codes.NOT_FOUND,
+                )
             logger.info(
                 "[purge] purging up to depth %i (received_ts %i => "
                 "stream_ordering %i)",


Test patch: