diff --git a/changelog.d/18020.misc b/changelog.d/18020.misc
new file mode 100644
index 0000000000000000000000000000000000000000..8d2dd883b919d1271fdb8d915a1901bfd42eae78
--- /dev/null
+++ b/changelog.d/18020.misc
@@ -0,0 +1 @@
+Remove some remaining uses of `twisted.internet.defer.returnValue`. Contributed by Colin Watson.
diff --git a/contrib/cmdclient/console.py b/contrib/cmdclient/console.py
index ca2e72b5e8e71c6556a28f647aeab48809ec89ae..9b5d33d2b1fb2cb273b92bd3d0dd28cb7a15d793 100755
--- a/contrib/cmdclient/console.py
+++ b/contrib/cmdclient/console.py
@@ -245,7 +245,7 @@ class SynapseCmd(cmd.Cmd):
 
         if "flows" not in json_res:
             print("Failed to find any login flows.")
-            defer.returnValue(False)
+            return False
 
         flow = json_res["flows"][0]  # assume first is the one we want.
         if "type" not in flow or "m.login.password" != flow["type"] or "stages" in flow:
@@ -254,8 +254,8 @@ class SynapseCmd(cmd.Cmd):
                 "Unable to login via the command line client. Please visit "
                 "%s to login." % fallback_url
             )
-            defer.returnValue(False)
-        defer.returnValue(True)
+            return False
+        return True
 
     def do_emailrequest(self, line):
         """Requests the association of a third party identifier
diff --git a/contrib/cmdclient/http.py b/contrib/cmdclient/http.py
index e6a10b5f3293696191c0cc7f04c049693b6b7731..54363e425921f02c07691557aafabca0ae1f6119 100644
--- a/contrib/cmdclient/http.py
+++ b/contrib/cmdclient/http.py
@@ -78,7 +78,7 @@ class TwistedHttpClient(HttpClient):
             url, data, headers_dict={"Content-Type": ["application/json"]}
         )
         body = yield readBody(response)
-        defer.returnValue((response.code, body))
+        return response.code, body
 
     @defer.inlineCallbacks
     def get_json(self, url, args=None):
@@ -88,7 +88,7 @@ class TwistedHttpClient(HttpClient):
             url = "%s?%s" % (url, qs)
         response = yield self._create_get_request(url)
         body = yield readBody(response)
-        defer.returnValue(json.loads(body))
+        return json.loads(body)
 
     def _create_put_request(self, url, json_data, headers_dict: Optional[dict] = None):
         """Wrapper of _create_request to issue a PUT request"""
@@ -134,7 +134,7 @@ class TwistedHttpClient(HttpClient):
             response = yield self._create_request(method, url)
 
         body = yield readBody(response)
-        defer.returnValue(json.loads(body))
+        return json.loads(body)
 
     @defer.inlineCallbacks
     def _create_request(
@@ -173,7 +173,7 @@ class TwistedHttpClient(HttpClient):
         if self.verbose:
             print("Status %s %s" % (response.code, response.phrase))
             print(pformat(list(response.headers.getAllRawHeaders())))
-        defer.returnValue(response)
+        return response
 
     def sleep(self, seconds):
         d = defer.Deferred()
diff --git a/synapse/logging/scopecontextmanager.py b/synapse/logging/scopecontextmanager.py
index 581e6d6411fc3d84214e2219bfe2831d6b324881..feaadc4d87ab8773e64515d06c23fda334d75516 100644
--- a/synapse/logging/scopecontextmanager.py
+++ b/synapse/logging/scopecontextmanager.py
@@ -20,13 +20,10 @@
 #
 
 import logging
-from types import TracebackType
-from typing import Optional, Type
+from typing import Optional
 
 from opentracing import Scope, ScopeManager, Span
 
-import twisted
-
 from synapse.logging.context import (
     LoggingContext,
     current_context,
@@ -112,9 +109,6 @@ class _LogContextScope(Scope):
     """
     A custom opentracing scope, associated with a LogContext
 
-      * filters out _DefGen_Return exceptions which arise from calling
-        `defer.returnValue` in Twisted code
-
       * When the scope is closed, the logcontext's active scope is reset to None.
         and - if enter_logcontext was set - the logcontext is finished too.
     """
@@ -146,17 +140,6 @@ class _LogContextScope(Scope):
         self._finish_on_close = finish_on_close
         self._enter_logcontext = enter_logcontext
 
-    def __exit__(
-        self,
-        exc_type: Optional[Type[BaseException]],
-        value: Optional[BaseException],
-        traceback: Optional[TracebackType],
-    ) -> None:
-        if exc_type == twisted.internet.defer._DefGen_Return:
-            # filter out defer.returnValue() calls
-            exc_type = value = traceback = None
-        super().__exit__(exc_type, value, traceback)
-
     def __str__(self) -> str:
         return f"Scope<{self.span}>"
 
diff --git a/synapse/util/patch_inline_callbacks.py b/synapse/util/patch_inline_callbacks.py
index 56bdf451dad822626a8351df13d1c58da5204e37..beea4d2888169cb2e637a69a4c134265d702f57e 100644
--- a/synapse/util/patch_inline_callbacks.py
+++ b/synapse/util/patch_inline_callbacks.py
@@ -162,7 +162,7 @@ def _check_yield_points(
                     d = result.throwExceptionIntoGenerator(gen)
                 else:
                     d = gen.send(result)
-            except (StopIteration, defer._DefGen_Return) as e:
+            except StopIteration as e:
                 if current_context() != expected_context:
                     # This happens when the context is lost sometime *after* the
                     # final yield and returning. E.g. we forgot to yield on a
@@ -183,7 +183,7 @@ def _check_yield_points(
                         )
                     )
                     changes.append(err)
-                # The `StopIteration` or `_DefGen_Return` contains the return value from the
+                # The `StopIteration` contains the return value from the
                 # generator.
                 return cast(T, e.value)