Repository: matrix-org/synapse

Issue:
UnboundLocalError: local variable 'result' referenced before assignment - on using Telegram bridge
I got the `UnboundLocalError: local variable 'result' referenced before assignment` error multiple times, it happens every time when I start Mautrix-Telegram AS bridge on homeserver, in Synapse logs they looks like this:
```
янв 27 20:08:26 tad python[11795]: 2018-01-27 20:08:26,131 - synapse.http.server - 145 - ERROR - POST-2331- Failed handle request synapse.http.server._async_render on <synapse.rest.ClientRestResource object at 0x7f9e3d39a550>: <SynapseRequest at 0x7f9e3419b368 method=POST uri=/_matrix/client/r0/register?user_id=%40telegram_94477076%3Ahomeserver.ru&access_token=<redacted> clientproto=HTTP/1.0 site=8008>: Traceback (most recent call last):
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 588, in _runCallbacks
янв 27 20:08:26 tad python[11795]:     current.result = callback(current.result, *args, **kw)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1184, in gotResult
янв 27 20:08:26 tad python[11795]:     _inlineCallbacks(r, g, deferred)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1126, in _inlineCallbacks
янв 27 20:08:26 tad python[11795]:     result = result.throwExceptionIntoGenerator(g)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/python/failure.py", line 389, in throwExceptionIntoGenerator
янв 27 20:08:26 tad python[11795]:     return g.throw(self.type, self.value, self.tb)
янв 27 20:08:26 tad python[11795]: --- <exception caught here> ---
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/synapse/http/server.py", line 117, in wrapped_request_handler
янв 27 20:08:26 tad python[11795]:     yield request_handler(self, request, request_metrics)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1126, in _inlineCallbacks
янв 27 20:08:26 tad python[11795]:     result = result.throwExceptionIntoGenerator(g)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/python/failure.py", line 389, in throwExceptionIntoGenerator
янв 27 20:08:26 tad python[11795]:     return g.throw(self.type, self.value, self.tb)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/synapse/http/server.py", line 263, in _async_render
янв 27 20:08:26 tad python[11795]:     callback_return = yield callback(request, **kwargs)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1128, in _inlineCallbacks
янв 27 20:08:26 tad python[11795]:     result = g.send(result)
янв 27 20:08:26 tad python[11795]:   File "/usr/lib/python2.7/dist-packages/synapse/rest/client/v2_alpha/register.py", line 240, in on_POST
янв 27 20:08:26 tad python[11795]:     defer.returnValue((200, result))  # we throw for non 200 responses
янв 27 20:08:26 tad python[11795]: exceptions.UnboundLocalError: local variable 'result' referenced before assignment
```
On Mautrix-Telegram side here is error report:
```
[2018-01-27 20:08:26,084] [DEBUG@mau.as.api] POST /join/%21VnRyoGslbQhPzSgQoZ%3Aqseo.ru None
[2018-01-27 20:08:26,115] [DEBUG@mau.as.api] POST /register {'type': {'username': 'telegram_94477076'}}
[2018-01-27 20:08:26,135] [ERROR@mau.as.intent] Failed to register @telegram_94477076:homeserver.ru!
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/mautrix_appservice/intent_api.py", line 306, in _ensure_registered
    self.client.register({"username": self.localpart})
  File "/usr/local/lib/python3.6/dist-packages/matrix_client/api.py", line 111, in register
    return self._send("POST", "/register", content)
  File "/usr/local/lib/python3.6/dist-packages/mautrix_appservice/intent_api.py", line 59, in _send
    return super()._send(method, path, content, query_params, headers, api_path=api_path)
  File "/usr/local/lib/python3.6/dist-packages/matrix_client/api.py", line 536, in _send
    code=response.status_code, content=response.text
matrix_client.errors.MatrixRequestError: 500: {"errcode":"M_UNKNOWN","error":"Internal server error"}
```


Discussion:
So the problem here is that mautrix-telegram isn't handing a valid `user` or `username` to the registration API.  @MurzNN can you find out what the JSON body is in the request it's making? Did you get it to work in the end?
The request body is in the logs: `POST /register {'type': {'username': 'telegram_94477076'}}`

After a bit of investigation, I found out that the problem on the mautrix-telegram side was using the `matrix-client` package from PyPI (well, I knew that already, but now I found out why). It's really outdated (last release March 2017) and the `register` method has [changed completely](https://github.com/matrix-org/matrix-python-sdk/commit/1dc2760ffdd1f457870806c4891c44ac75077ff7) after the release. I didn't realize that because I just looked at the code on `master` for documentation. Separate release-specific official docs (matrix-org/matrix-python-sdk#138) would probably be a good idea.

Anyway, the problem with synapse here is the internal server error. That shouldn't happen: it's a bad request, not an internal server error.

Resolving patch:
diff --git a/synapse/rest/client/v2_alpha/register.py b/synapse/rest/client/v2_alpha/register.py
--- a/synapse/rest/client/v2_alpha/register.py
+++ b/synapse/rest/client/v2_alpha/register.py
@@ -431,11 +431,14 @@ async def on_POST(self, request):
 
             access_token = self.auth.get_access_token_from_request(request)
 
-            if isinstance(desired_username, str):
-                result = await self._do_appservice_registration(
-                    desired_username, access_token, body
-                )
-            return 200, result  # we throw for non 200 responses
+            if not isinstance(desired_username, str):
+                raise SynapseError(400, "Desired Username is missing or not a string")
+
+            result = await self._do_appservice_registration(
+                desired_username, access_token, body
+            )
+
+            return 200, result
 
         # == Normal User Registration == (everyone else)
         if not self._registration_enabled:


Test patch: