# Buggy code
def respond_with_json_bytes(
    request: Request,
    code: int,
    json_bytes: bytes,
    send_cors: bool = False,
):
    """Sends encoded JSON in response to the given request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        json_bytes: The json bytes to use as the response body.
        send_cors: Whether to send Cross-Origin Resource Sharing headers
            https://fetch.spec.whatwg.org/#http-cors-protocol

    Returns:
        twisted.web.server.NOT_DONE_YET if the request is still active.
    """

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"application/json")
    request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),))
    request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate")

    if send_cors:
        set_cors_headers(request)

    # note that this is zero-copy (the bytesio shares a copy-on-write buffer with
    # the original `bytes`).
    bytes_io = BytesIO(json_bytes)

    producer = NoRangeStaticProducer(request, bytes_io)
    producer.start()
    return NOT_DONE_YET


# Traceback (AttributeError)
2019-05-31 11:55:56,270 - synapse.access.http.8008 - 233 - INFO - GET-1116745- 176.14.254.64 - 8008 - Received request: GET /_matrix/media/v1/thumbnail/amorgan.xyz/JpHpuDNOxuALIaPSENEAzZIu?width=800&amp;height=600
2019-05-31 11:55:56,273 - synapse.access.http.8008 - 302 - INFO - GET-1116745- 176.14.254.64 - 8008 - {None} Processed request: 0.003sec/-0.000sec (0.000sec, 0.000sec) (0.000sec/0.001sec/2) 92715B 200 "GET /_matrix/media/v1/thumbnail/amorgan.xyz/JpHpuDNOxuALIaPSENEAzZIu?width=800&amp;height=600 HTTP/1.0" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0" [0 dbevts]
2019-05-31 11:55:56,321 - synapse.access.http.8008 - 233 - INFO - GET-1116746- 176.14.254.64 - 8008 - Received request: GET /_matrix/media/v1/thumbnail/amorgan.xyz/chzgDJfCkiDOFITyulcRWQOn?width=40&amp;height=40&amp;method=crop
2019-05-31 11:55:56,322 - synapse.http.site - 203 - WARNING - GET-1116746- Error processing request <XForwardedForRequest at 0x7feb7a25e860 method='GET' uri='/_matrix/media/v1/thumbnail/amorgan.xyz/chzgDJfCkiDOFITyulcRWQOn?width=40&amp;height=40&amp;method=crop' clientproto='HTTP/1.0' site=8008>: <class 'twisted.internet.error.ConnectionDone'> Connection was closed cleanly.
2019-05-31 11:55:56,325 - synapse.rest.media.v1._base - 192 - WARNING - GET-1116746- Failed to write to consumer: <class 'AttributeError'> 'NoneType' object has no attribute 'registerProducer'
2019-05-31 11:55:56,325 - synapse.http.server - 112 - ERROR - GET-1116746- Failed handle request via 'ThumbnailResource': <XForwardedForRequest at 0x7feb7a25e860 method='GET' uri='/_matrix/media/v1/thumbnail/amorgan.xyz/chzgDJfCkiDOFITyulcRWQOn?width=40&amp;height=40&amp;method=crop' clientproto='HTTP/1.0' site=8008>
Traceback (most recent call last):
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/storage/_base.py", line 527, in runWithConnection
defer.returnValue(result)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1362, in returnValue
raise _DefGen_Return(val)
twisted.internet.defer._DefGen_Return: [{'thumbnail_width': 32, 'thumbnail_type': 'image/png', 'thumbnail_height': 32, 'thumbnail_length': 2341, 'thumbnail_method': 'crop'}, {'thumbnail_width': 239, 'thumbnail_type': 'image/png', 'thumbnail_height': 240, 'thumbnail_length': 84450, 'thumbnail_method': 'scale'}, {'thumbnail_width': 399, 'thumbnail_type': 'image/png', 'thumbnail_height': 400, 'thumbnail_length': 196365, 'thumbnail_method': 'scale'}, {'thumbnail_width': 96, 'thumbnail_type': 'image/png', 'thumbnail_height': 96, 'thumbnail_length': 16151, 'thumbnail_method': 'crop'}]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/storage/_base.py", line 487, in runInteraction
defer.returnValue(result)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1362, in returnValue
raise _DefGen_Return(val)
twisted.internet.defer._DefGen_Return: [{'thumbnail_width': 32, 'thumbnail_type': 'image/png', 'thumbnail_height': 32, 'thumbnail_length': 2341, 'thumbnail_method': 'crop'}, {'thumbnail_width': 239, 'thumbnail_type': 'image/png', 'thumbnail_height': 240, 'thumbnail_length': 84450, 'thumbnail_method': 'scale'}, {'thumbnail_width': 399, 'thumbnail_type': 'image/png', 'thumbnail_height': 400, 'thumbnail_length': 196365, 'thumbnail_method': 'scale'}, {'thumbnail_width': 96, 'thumbnail_type': 'image/png', 'thumbnail_height': 96, 'thumbnail_length': 16151, 'thumbnail_method': 'crop'}]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/rest/media/v1/_base.py", line 187, in respond_with_responder
yield responder.write_to_consumer(request)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/rest/media/v1/media_storage.py", line 263, in write_to_consumer
FileSender().beginFileTransfer(self.open_file, consumer)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/protocols/basic.py", line 923, in beginFileTransfer
self.consumer.registerProducer(self, False)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/web/http.py", line 961, in registerProducer
self.channel.registerProducer(producer, streaming)
AttributeError: 'NoneType' object has no attribute 'registerProducer'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/http/server.py", line 81, in wrapped_request_handler
yield h(self, request)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 71, in _async_render_GET
request, media_id, width, height, method, m_type
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/rest/media/v1/thumbnail_resource.py", line 121, in _respond_local_thumbnail
yield respond_with_responder(request, responder, t_type, t_length)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/internet/defer.py", line 1418, in _inlineCallbacks
result = g.send(result)
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/synapse/rest/media/v1/_base.py", line 196, in respond_with_responder
request.unregisterProducer()
File "/home/ops/.synapse3/env3/lib/python3.5/site-packages/twisted/web/http.py", line 967, in unregisterProducer
self.channel.unregisterProducer()
AttributeError: 'NoneType' object has no attribute 'unregisterProducer'
2019-05-31 11:55:56,326 - synapse.http.server - 415 - WARNING - GET-1116746- Not sending response to request <XForwardedForRequest at 0x7feb7a25e860 method='GET' uri='/_matrix/media/v1/thumbnail/amorgan.xyz/chzgDJfCkiDOFITyulcRWQOn?width=40&amp;height=40&amp;method=crop' clientproto='HTTP/1.0' site=8008>, already disconnected.
2019-05-31 11:55:56,326 - synapse.access.http.8008 - 302 - INFO - GET-1116746- 176.14.254.64 - 8008 - {None} Processed request: 0.005sec/-0.004sec (0.000sec, 0.000sec) (0.001sec/0.002sec/2) 0B 200! "GET /_matrix/media/v1/thumbnail/amorgan.xyz/chzgDJfCkiDOFITyulcRWQOn?width=40&amp;height=40&amp;method=crop HTTP/1.0" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0" [0 dbevts]

# Fixed code
def respond_with_json_bytes(
    request: Request,
    code: int,
    json_bytes: bytes,
    send_cors: bool = False,
):
    """Sends encoded JSON in response to the given request.

    Args:
        request: The http request to respond to.
        code: The HTTP response code.
        json_bytes: The json bytes to use as the response body.
        send_cors: Whether to send Cross-Origin Resource Sharing headers
            https://fetch.spec.whatwg.org/#http-cors-protocol

    Returns:
        twisted.web.server.NOT_DONE_YET if the request is still active.
    """
    if request._disconnected:
        logger.warning(
            "Not sending response to request %s, already disconnected.", request
        )
        return

    request.setResponseCode(code)
    request.setHeader(b"Content-Type", b"application/json")
    request.setHeader(b"Content-Length", b"%d" % (len(json_bytes),))
    request.setHeader(b"Cache-Control", b"no-cache, no-store, must-revalidate")

    if send_cors:
        set_cors_headers(request)

    # note that this is zero-copy (the bytesio shares a copy-on-write buffer with
    # the original `bytes`).
    bytes_io = BytesIO(json_bytes)

    producer = NoRangeStaticProducer(request, bytes_io)
    producer.start()
    return NOT_DONE_YET