prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  /displayname returns non-JSON body
  ### Description
  
  An attempt to call `/profile/{}/displayname` with an empty body results (rightfully) in a 400 error, with plain text "Unable to parse name" in the response. The expected error payload is something about (could also be `M_NOT_JSON` instead of `M_BAD_JSON`):
  ```json
  {
      "errcode": "M_BAD_JSON",
      "error": "Unable to parse name" 
  }
  ```
  
  ### Version information
  
  <!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
  
  <!-- Was this issue identified on matrix.org or another homeserver? -->
  - **Homeserver**: matrix.org
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `synapse/rest/client/v1/profile.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 # Copyright 2014-2016 OpenMarket Ltd
  3 #
  4 # Licensed under the Apache License, Version 2.0 (the "License");
  5 # you may not use this file except in compliance with the License.
  6 # You may obtain a copy of the License at
  7 #
  8 #     http://www.apache.org/licenses/LICENSE-2.0
  9 #
  10 # Unless required by applicable law or agreed to in writing, software
  11 # distributed under the License is distributed on an "AS IS" BASIS,
  12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 # See the License for the specific language governing permissions and
  14 # limitations under the License.
  15 
  16 """ This module contains REST servlets to do with profile: /profile/<paths> """
  17 
  18 from synapse.api.errors import Codes, SynapseError
  19 from synapse.http.servlet import RestServlet, parse_json_object_from_request
  20 from synapse.rest.client.v2_alpha._base import client_patterns
  21 from synapse.types import UserID
  22 
  23 
  24 class ProfileDisplaynameRestServlet(RestServlet):
  25     PATTERNS = client_patterns("/profile/(?P<user_id>[^/]*)/displayname", v1=True)
  26 
  27     def __init__(self, hs):
  28         super().__init__()
  29         self.hs = hs
  30         self.profile_handler = hs.get_profile_handler()
  31         self.auth = hs.get_auth()
  32 
  33     async def on_GET(self, request, user_id):
  34         requester_user = None
  35 
  36         if self.hs.config.require_auth_for_profile_requests:
  37             requester = await self.auth.get_user_by_req(request)
  38             requester_user = requester.user
  39 
  40         user = UserID.from_string(user_id)
  41 
  42         await self.profile_handler.check_profile_query_allowed(user, requester_user)
  43 
  44         displayname = await self.profile_handler.get_displayname(user)
  45 
  46         ret = {}
  47         if displayname is not None:
  48             ret["displayname"] = displayname
  49 
  50         return 200, ret
  51 
  52     async def on_PUT(self, request, user_id):
  53         requester = await self.auth.get_user_by_req(request, allow_guest=True)
  54         user = UserID.from_string(user_id)
  55         is_admin = await self.auth.is_server_admin(requester.user)
  56 
  57         content = parse_json_object_from_request(request)
  58 
  59         try:
  60             new_name = content["displayname"]
  61         except Exception:
  62             return 400, "Unable to parse name"
  63 
  64         await self.profile_handler.set_displayname(user, requester, new_name, is_admin)
  65 
  66         return 200, {}
  67 
  68     def on_OPTIONS(self, request, user_id):
  69         return 200, {}
  70 
  71 
  72 class ProfileAvatarURLRestServlet(RestServlet):
  73     PATTERNS = client_patterns("/profile/(?P<user_id>[^/]*)/avatar_url", v1=True)
  74 
  75     def __init__(self, hs):
  76         super().__init__()
  77         self.hs = hs
  78         self.profile_handler = hs.get_profile_handler()
  79         self.auth = hs.get_auth()
  80 
  81     async def on_GET(self, request, user_id):
  82         requester_user = None
  83 
  84         if self.hs.config.require_auth_for_profile_requests:
  85             requester = await self.auth.get_user_by_req(request)
  86             requester_user = requester.user
  87 
  88         user = UserID.from_string(user_id)
  89 
  90         await self.profile_handler.check_profile_query_allowed(user, requester_user)
  91 
  92         avatar_url = await self.profile_handler.get_avatar_url(user)
  93 
  94         ret = {}
  95         if avatar_url is not None:
  96             ret["avatar_url"] = avatar_url
  97 
  98         return 200, ret
  99 
  100     async def on_PUT(self, request, user_id):
  101         requester = await self.auth.get_user_by_req(request)
  102         user = UserID.from_string(user_id)
  103         is_admin = await self.auth.is_server_admin(requester.user)
  104 
  105         content = parse_json_object_from_request(request)
  106         try:
  107             new_avatar_url = content["avatar_url"]
  108         except KeyError:
  109             raise SynapseError(
  110                 400, "Missing key 'avatar_url'", errcode=Codes.MISSING_PARAM
  111             )
  112 
  113         await self.profile_handler.set_avatar_url(
  114             user, requester, new_avatar_url, is_admin
  115         )
  116 
  117         return 200, {}
  118 
  119     def on_OPTIONS(self, request, user_id):
  120         return 200, {}
  121 
  122 
  123 class ProfileRestServlet(RestServlet):
  124     PATTERNS = client_patterns("/profile/(?P<user_id>[^/]*)", v1=True)
  125 
  126     def __init__(self, hs):
  127         super().__init__()
  128         self.hs = hs
  129         self.profile_handler = hs.get_profile_handler()
  130         self.auth = hs.get_auth()
  131 
  132     async def on_GET(self, request, user_id):
  133         requester_user = None
  134 
  135         if self.hs.config.require_auth_for_profile_requests:
  136             requester = await self.auth.get_user_by_req(request)
  137             requester_user = requester.user
  138 
  139         user = UserID.from_string(user_id)
  140 
  141         await self.profile_handler.check_profile_query_allowed(user, requester_user)
  142 
  143         displayname = await self.profile_handler.get_displayname(user)
  144         avatar_url = await self.profile_handler.get_avatar_url(user)
  145 
  146         ret = {}
  147         if displayname is not None:
  148             ret["displayname"] = displayname
  149         if avatar_url is not None:
  150             ret["avatar_url"] = avatar_url
  151 
  152         return 200, ret
  153 
  154 
  155 def register_servlets(hs, http_server):
  156     ProfileDisplaynameRestServlet(hs).register(http_server)
  157     ProfileAvatarURLRestServlet(hs).register(http_server)
  158     ProfileRestServlet(hs).register(http_server)
  159
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/synapse/rest/client/v1/profile.py b/synapse/rest/client/v1/profile.py
  --- a/synapse/rest/client/v1/profile.py
  +++ b/synapse/rest/client/v1/profile.py
  @@ -59,7 +59,9 @@
           try:
               new_name = content["displayname"]
           except Exception:
  -            return 400, "Unable to parse name"
  +            raise SynapseError(
  +                code=400, msg="Unable to parse name", errcode=Codes.BAD_JSON,
  +            )
   
           await self.profile_handler.set_displayname(user, requester, new_name, is_admin)
  
verification_info: {"golden_diff": "diff --git a/synapse/rest/client/v1/profile.py b/synapse/rest/client/v1/profile.py\n--- a/synapse/rest/client/v1/profile.py\n+++ b/synapse/rest/client/v1/profile.py\n@@ -59,7 +59,9 @@\n         try:\n             new_name = content[\"displayname\"]\n         except Exception:\n-            return 400, \"Unable to parse name\"\n+            raise SynapseError(\n+                code=400, msg=\"Unable to parse name\", errcode=Codes.BAD_JSON,\n+            )\n \n         await self.profile_handler.set_displayname(user, requester, new_name, is_admin)\n", "issue": "/displayname returns non-JSON body\n### Description\r\n\r\nAn attempt to call `/profile/{}/displayname` with an empty body results (rightfully) in a 400 error, with plain text \"Unable to parse name\" in the response. The expected error payload is something about (could also be `M_NOT_JSON` instead of `M_BAD_JSON`):\r\n```json\r\n{\r\n    \"errcode\": \"M_BAD_JSON\",\r\n    \"error\": \"Unable to parse name\" \r\n}\r\n```\r\n\r\n### Version information\r\n\r\n<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->\r\n\r\n<!-- Was this issue identified on matrix.org or another homeserver? -->\r\n- **Homeserver**: matrix.org\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2014-2016 OpenMarket Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\" This module contains REST servlets to do with profile: /profile/<paths> \"\"\"\n\nfrom synapse.api.errors import Codes, SynapseError\nfrom synapse.http.servlet import RestServlet, parse_json_object_from_request\nfrom synapse.rest.client.v2_alpha._base import client_patterns\nfrom synapse.types import UserID\n\n\nclass ProfileDisplaynameRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)/displayname\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        displayname = await self.profile_handler.get_displayname(user)\n\n        ret = {}\n        if displayname is not None:\n            ret[\"displayname\"] = displayname\n\n        return 200, ret\n\n    async def on_PUT(self, request, user_id):\n        requester = await self.auth.get_user_by_req(request, allow_guest=True)\n        user = UserID.from_string(user_id)\n        is_admin = await self.auth.is_server_admin(requester.user)\n\n        content = parse_json_object_from_request(request)\n\n        try:\n            new_name = content[\"displayname\"]\n        except Exception:\n            return 400, \"Unable to parse name\"\n\n        await self.profile_handler.set_displayname(user, requester, new_name, is_admin)\n\n        return 200, {}\n\n    def on_OPTIONS(self, request, user_id):\n        return 200, {}\n\n\nclass ProfileAvatarURLRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)/avatar_url\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        avatar_url = await self.profile_handler.get_avatar_url(user)\n\n        ret = {}\n        if avatar_url is not None:\n            ret[\"avatar_url\"] = avatar_url\n\n        return 200, ret\n\n    async def on_PUT(self, request, user_id):\n        requester = await self.auth.get_user_by_req(request)\n        user = UserID.from_string(user_id)\n        is_admin = await self.auth.is_server_admin(requester.user)\n\n        content = parse_json_object_from_request(request)\n        try:\n            new_avatar_url = content[\"avatar_url\"]\n        except KeyError:\n            raise SynapseError(\n                400, \"Missing key 'avatar_url'\", errcode=Codes.MISSING_PARAM\n            )\n\n        await self.profile_handler.set_avatar_url(\n            user, requester, new_avatar_url, is_admin\n        )\n\n        return 200, {}\n\n    def on_OPTIONS(self, request, user_id):\n        return 200, {}\n\n\nclass ProfileRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        displayname = await self.profile_handler.get_displayname(user)\n        avatar_url = await self.profile_handler.get_avatar_url(user)\n\n        ret = {}\n        if displayname is not None:\n            ret[\"displayname\"] = displayname\n        if avatar_url is not None:\n            ret[\"avatar_url\"] = avatar_url\n\n        return 200, ret\n\n\ndef register_servlets(hs, http_server):\n    ProfileDisplaynameRestServlet(hs).register(http_server)\n    ProfileAvatarURLRestServlet(hs).register(http_server)\n    ProfileRestServlet(hs).register(http_server)\n", "path": "synapse/rest/client/v1/profile.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2014-2016 OpenMarket Ltd\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\" This module contains REST servlets to do with profile: /profile/<paths> \"\"\"\n\nfrom synapse.api.errors import Codes, SynapseError\nfrom synapse.http.servlet import RestServlet, parse_json_object_from_request\nfrom synapse.rest.client.v2_alpha._base import client_patterns\nfrom synapse.types import UserID\n\n\nclass ProfileDisplaynameRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)/displayname\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        displayname = await self.profile_handler.get_displayname(user)\n\n        ret = {}\n        if displayname is not None:\n            ret[\"displayname\"] = displayname\n\n        return 200, ret\n\n    async def on_PUT(self, request, user_id):\n        requester = await self.auth.get_user_by_req(request, allow_guest=True)\n        user = UserID.from_string(user_id)\n        is_admin = await self.auth.is_server_admin(requester.user)\n\n        content = parse_json_object_from_request(request)\n\n        try:\n            new_name = content[\"displayname\"]\n        except Exception:\n            raise SynapseError(\n                code=400, msg=\"Unable to parse name\", errcode=Codes.BAD_JSON,\n            )\n\n        await self.profile_handler.set_displayname(user, requester, new_name, is_admin)\n\n        return 200, {}\n\n    def on_OPTIONS(self, request, user_id):\n        return 200, {}\n\n\nclass ProfileAvatarURLRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)/avatar_url\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        avatar_url = await self.profile_handler.get_avatar_url(user)\n\n        ret = {}\n        if avatar_url is not None:\n            ret[\"avatar_url\"] = avatar_url\n\n        return 200, ret\n\n    async def on_PUT(self, request, user_id):\n        requester = await self.auth.get_user_by_req(request)\n        user = UserID.from_string(user_id)\n        is_admin = await self.auth.is_server_admin(requester.user)\n\n        content = parse_json_object_from_request(request)\n        try:\n            new_avatar_url = content[\"avatar_url\"]\n        except KeyError:\n            raise SynapseError(\n                400, \"Missing key 'avatar_url'\", errcode=Codes.MISSING_PARAM\n            )\n\n        await self.profile_handler.set_avatar_url(\n            user, requester, new_avatar_url, is_admin\n        )\n\n        return 200, {}\n\n    def on_OPTIONS(self, request, user_id):\n        return 200, {}\n\n\nclass ProfileRestServlet(RestServlet):\n    PATTERNS = client_patterns(\"/profile/(?P<user_id>[^/]*)\", v1=True)\n\n    def __init__(self, hs):\n        super().__init__()\n        self.hs = hs\n        self.profile_handler = hs.get_profile_handler()\n        self.auth = hs.get_auth()\n\n    async def on_GET(self, request, user_id):\n        requester_user = None\n\n        if self.hs.config.require_auth_for_profile_requests:\n            requester = await self.auth.get_user_by_req(request)\n            requester_user = requester.user\n\n        user = UserID.from_string(user_id)\n\n        await self.profile_handler.check_profile_query_allowed(user, requester_user)\n\n        displayname = await self.profile_handler.get_displayname(user)\n        avatar_url = await self.profile_handler.get_avatar_url(user)\n\n        ret = {}\n        if displayname is not None:\n            ret[\"displayname\"] = displayname\n        if avatar_url is not None:\n            ret[\"avatar_url\"] = avatar_url\n\n        return 200, ret\n\n\ndef register_servlets(hs, http_server):\n    ProfileDisplaynameRestServlet(hs).register(http_server)\n    ProfileAvatarURLRestServlet(hs).register(http_server)\n    ProfileRestServlet(hs).register(http_server)\n", "path": "synapse/rest/client/v1/profile.py"}]}